Debugger Limitations

Index of All Documentation » Wing Pro Reference Manual » Advanced Debugging Topics »


If you are having problems getting the debugger to stop at breakpoints or to display source as you step through your code, always read the Trouble-shooting Failure to Debug section first.

This section documents all know limitations in the debugger implementation. Many of these are extremely rare and esoteric:

(1) Your source files must be stored on disk and accessible to the IDE. If you are trying to debug code fragments, try writing them to disk temporarily and setting the __file__ variable in the module name space before invoking Python's exec or eval. This will allow Wing's debugger to map code objects to the source you've temporarily written to disk.

(2) Running without saving will lead to incorrect display of breakpoints and run position because the debug process runs against the on-disk version of the source file. Wing will indicate that some files are out of sync so this case should only occur if you ignore its warnings.

(3) There are several cases where Wing may fail to stop at breakpoints or exceptions, or may fail to find source files. All of these are caused by storage of incorrect file names in *.pyc files:

  • Moving *.pyc files on disk after they are generated invalidates the file name stored in the file if it is a partial relative path. This happens if your PYTHONPATH or sys.path contains partial relative path names.
  • A similar problem may result from use of compileall.py and some other utilities that don't record a correct filename in the *.pyc file.
  • If you run the same code twice using different paths to the same working directory, as is possible on Linux and macOS with symbolic links, the file names left in *.pyc may contain a mix of each of these paths. If the symbolic link that was used is subsequently removed, some of the file names become invalid.

The fix for all of these problems is to remove the *.pyc files and let Python regenerate them from the corresponding *.py files with the correct file name information.

Hint: You can open *.pyc files in most text editors to inspect the stored file names.

(4) For code that spends much of its time in C/C++ without calling Python at all, the debugger may not reliably stop at breakpoints added during a run session, and may not respond to Pause requests. See Debugging Non-Python Mainloops for details.

(5) You cannot use pdb or other debuggers together with Wing's debugger. The two debuggers conflict because they attempt to use the same debug tracer in the Python interpreter.

(6) If you override __import__ in your code, you will break the debugger's ability to stop at breakpoints unless you call the original __import__ as part of your code whenever a module is actually imported. If you cannot call the original __import__ for some reason, it may be possible to instead use wingdbstub and then call wingdbstub.debugger.NotifyImport(mod) from your import handler, where mod is the module that was just imported.

(7) If you set __file__ in a module's name space to a value other than its original, Wing will be unable to stop at breakpoints in the module and may fail to report exceptions to the IDE's user interface.

(8) If you use an extension module to call C/C++ level stdio calls instead of using the Python-level facilities, the debug process will remain unresponsive to Wing while waiting for keyboard input, I/O redirection to the Debug Console in Wing Pro will fail, and you may run into out-of-order character reads in some cases. Details can be found in Debug Process I/O.

(9) Using partial path names in module __file__ attributes can in rare cases cause Wing to fail to stop on breakpoints and exceptions, to fail to display source files, or to confuse source files of the same name.

A partial path name may end up in __file__ only when (a) invoking Python code with a partial path name, for example with python myfile.py instead of python /path/to/myfile.py, (b) sending partial path names into exec, (c) using partial path names in your PYTHONPATH or sys.path, or (d) using compileall.py or similar tool to compile modules with a partial path name.

Because Wing does everything possible to avoid this problem in practice, it actually only occurs in the following rare cases:

  • When modules are loaded with partial path names and os.chdir() is called before debugging is started. This is only possible when using wingdbstub.
  • When modules are loaded with partial path names and os.chdir() is called after wingdbstub.debugger.SuspendDebug() and before wingdbstub.debugger.ResumeDebug().
  • When modules are loaded with partial path names and removed from sys.modules before the debugger is started or while debugging is suspended.
  • When code objects are created on the fly using compile() or the C API, a relative filename or an incorrect filename are used for the filename argument, and os.chdir() is called before the code is executed.

(10) Wing tries to identify when source code in the IDE matches or does not match the code that is running in the debug process. There are certain very rare cases where this will fail, which may lead to failure to stop on breakpoints and other problems even when files are identified by the IDE as being synchronized:

Using execfile(), eval(), or exec with a globals dict that contains __file__ will cause Wing to incorrectly assert that the specified file has been reloaded. In practice, this scenario usually occurs when execfile() is called from the top level of a module, in which case the module is in fact being loaded or reloaded (so no mis-identification of module load status occurs). However, in cases where a module load takes a long time or involves a long-running loop at the top level, the execfile(), eval(), or exec may occur after edits to the module have been made and saved. In this case, Wing will mis-identify the module as having been reloaded with the new edits.

This problem can also be triggered if a globals with __file__ is explicitly passed to execfile(), eval(), or exec. However, it will only occur in this case when the code object file name is ?, and locals and globals dictionaries are the same, as they are by default for these calls.

(11) Naming a file <string> will prevent the debugger from debugging that file because it is confused with the default file name used in Python for code that is not located in a file.

(12) The debugger may fail to step or start after stopping at a breakpoint if the floating point mode is set to single precision (24 bit) on Intel x86 and potentially other processors. This is sometimes done by graphics libraries such as DirectX or by other code that optimizes floating point calculations.