Chapter 5. Debugging
At some point in their career, most
programmers realize that their job title should be "senior
debugger" instead of senior developer. Debugging is the art of
getting your code to run as you intended, instead of running as
you wrote it. That is the nub, really—in most cases it's your code
that is wrong. Python itself is pretty flawless — there are
hardly any noticeable bugs left. The same goes for Qt. PyQt might
still have a few bugs in it, but you would have to be using
decidedly advanced features to stumble onto them. In most cases,
your own ‘undocumented features' will be your undoing.
In this chapter we'll use the debugger
included in BlackAdder to find bugs in
some simple scripts. If you don't understand the actual code yet,
don't worry — you can always come back later. The main goal
is to familiarize yourself with the BlackAdder environment and the
concept of debugging.
There are two basic methods of debugging. The
first is sprinkling your code with print
statements that dump the contents of the variables of your
application. The second method is to follow your application as it
executes using a good debugger, examining the application data
using the tools the debugger provides.
Python has always been possessed of a basic
command-line based debugger, pdb,
similar to the infamous Unix debuggers,
dbx and gdb.
If you've ever tried to actually trace an application using one of
these, you'll know the exact meaning of the word ‘inconvenient'.
Using them is on a par with using ed or
edlin — both line editors —
for editing code.
To show a session with pdb:
Python 2.1.1 (#1, Aug 11 2001, 20:14:53)
[GCC 2.95.2 19991024 (release)] on linux2
Type "copyright", "credits" or "license" for more information.
>>> import pdb
>>> import button
>>> pdb.run("button.main([])")
> /home/boudewijn/doc/pyqt/ch23/<string>(0)?()
(Pdb) continue
> /home/boudewijn/doc/pyqt/ch23/<string>(1)?()
(Pdb) continue
Traceback (most recent call last):
File "button.py", line 26, in slotSlot
i = 1/0
ZeroDivisionError: integer division or modulo by zero
--Return--
> /home/boudewijn/doc/pyqt/ch23/<string>(1)?()->None
(Pdb) w
> /home/boudewijn/doc/pyqt/ch23/<string>(1)?()->None
(Pdb) l
[EOF]
(Pdb) q
>>>
You can see why there have been many attempts
to create a useful GUI fronted to pdb.
Most have suffered from the fact that they don't know where to
stop debugging. If you are debugging a piece of code that contains
the statement string.join(), you probably
don't want to single-step into the string.py
module, which is part of the Python system library—and yet
this is exactly what happens very often.
BlackAdder
includes a very nice debugger, one that knows where to stop
debugging. It includes all the usual facilities, like
single-stepping, breakpoints and a watch panel for variable
values.
Currently missing features include
conditional breakpoints (a breakpoint that only breaks execution
on certain values for certain variables) and runtime code changes.
You can change variable values runtime using the Python
interpreter window, though.
The PyQt library includes another, simpler
debugger, called eric. This application
is no longer maintained, so I won't spend much time here
describing the way it works. It does, however, provide a very nice
example of using regular expressions and PyQt's
QCanvas widget. You can start
eric by typing
eric on the command-line.
Running scripts
The BlackAdder toolbar has two buttons for debugging your
code. You can either debug a single script, or the whole
project.
One thing to be aware of when running
scripts or projects from BlackAdder
is that everything you print or write to
standard error or standard output gets lost, unless you have the
Python interpreter window active. Eric also prints the output to
the Python shell window.