Sunday, January 31, 2010

Debugging Techniques for IronPython: Breakpoints

Currently, programs IronPython is not particularly easy to debug – they Python code gets mixed in with the code for IronPython itself and can be hard to follow. This is the first of a few tricks to make debugging easier.

Trigger a Breakpoint

This is my favourite and most used technique – I sometimes wish Python had the equivalent of JavaScript's debugger keyword to make it easier to use. The trick is to use the System.Diagnostics.Debugger.Break() function to insert a breakpoint in your code – when the breakpoint is hit, Windows will offer to launch a debugger for you. Also make sure that you launch IronPython with the –X:Debug switch, or it will be next to impossible to debug.

Insert the following line where you want to trigger the breakpoint:

import System.Diagnostics; System.Diagnostics.Debugger.Break()

Windows will then open the following dialog (if you have Visual Studio installed; I don't have a machine without VS to see what it looks like otherwise):

vsjitbdgr

I prefer to use VS for debugging, so I'll open a  new instance of Visual Studio 2008.

Browsing the Call Stack

Now, we'll need to go looking for the actual Python code in the call stack. Open the call stack browser, and you'll see something like this:

dbgrbrk

There are a few things to note here, especially if you're not familiar with the VS debugger:

  • Each line represents a call stack frame (a function call, basically).
  • The yellow arrow is the current execution location; this is our breakpoint.
  • Faded-out lines are frames that do not have any debug information available. They can be ignored.
  • Lines beginning with "Snippets.debug" are the actual Python stack frames we are looking for. Double click on those lines to open up the source for those files in the Visual Studio editor.

Once the Python source is loaded in the editor, you can inspect variable values by hovering over them with the mouse, just like in any other Visual Studio language. To find the calling stack frame, you'll have to skip over several IronPython frames to find the next Python frame.

A better experience would elide the IronPython frames; perhaps Harry Pierson's debugger work could be applied to improve it. That, and other Visual Studio improvements for IronPython, are another project entirely.