It Crashes!¶
When we encounter failures in our code, we call them bugs, and we call the process of fixing them debugging.
Normally a programmer runs their program either from an IDE (such as PyScripter, PyDev, PyCharm, Eric, etc) or they run it from the command line, so that they can directly see traceback information:
$ python exercises/heartclick/crash.py
Traceback (most recent call last):
File "exercises/heartclick/crash.py", line 7, in <module>
raise RuntimeError("Moo")
RuntimeError: Moo
But since we can’t do that with TDSB student accounts, we’ll have to work around it.
Why did it crash?¶
To catch the output of our script without being able to run our script from the command line we can do this:
>>> import subprocess,os
>>> output,_ = subprocess.Popen(
... ['python','h:\\heartclick.py'],
... stdout=subprocess.PIPE,
... stderr=subprocess.STDOUT
... ).communicate()
>>> print output
Traceback (most recent call last):
File "exercises/heartclick/game.py", line 7, in <module>
raise RuntimeError("Moo")
RuntimeError: Moo
that lets us run our script and see all of its output, but only after the
game exits. The subprocess
module allows us to run commands as though we
had a console.
We can also store this in a script that we can double-click:
import subprocess,os
output,_ = subprocess.Popen(
['python','h:\\heartclick.py'],
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT
).communicate()
print(output)
input('Hit <enter> to close: ')
Pause Before Crash-exit¶
We can install a “hook” in our game as sys.excepthook()
so that the console doesn’t just close on failures, but instead lets you read
the traceback and asks you to hit <enter> to close the console.
import sys
def print_and_wait(type,value,traceback):
sys.__excepthook__(type,value,traceback)
input("Press <enter> to close: ")
sys.excepthook = print_and_wait
Debugging/Line by Line¶
You can also try stepping through your game line-by-line to see what is happening:
import pdb
pdb.set_trace()
When those lines are encountered (called a breakpoint) the debugger will start and let you step through your code line-by-line. The major commands you’ll want to use are:
n – next line
c – continue to run the script without pausing at each line (until the next breakpoint)
q – quit exit and cause the script to crash/close
p <something> – print out a variable
Here’s what a debugging session looks like:
> /home/mcfletch/2daypython/exercises/heartclick/game.py(9)<module>()
-> clock = pygame.time.Clock()
(Pdb) n
> /home/mcfletch/2daypython/exercises/heartclick/game.py(12)<module>()
-> screen = pygame.display.set_mode((300, 300))
(Pdb) n
> /home/mcfletch/2daypython/exercises/heartclick/game.py(13)<module>()
-> pygame.display.init()
(Pdb) p screen
<Surface(300x300x32 SW)>
(Pdb) n
> /home/mcfletch/2daypython/exercises/heartclick/game.py(21)<module>()
-> import os
(Pdb)
> /home/mcfletch/2daypython/exercises/heartclick/game.py(24)<module>()
-> HERE = os.path.dirname(__file__)
(Pdb) n
> /home/mcfletch/2daypython/exercises/heartclick/game.py(27)<module>()
-> heart_filename = os.path.join(HERE,'heart.png')
(Pdb) p HERE
'exercises/heartclick'
(Pdb) q
pdb
is a very basic debugger with simple command-line controls.