Introduction
Code is never perfect. You will always have bugs. Code debugging is a skill you need to learn.
Code is never perfect. You will always have bugs. Code debugging is a skill you need to learn.
So, your program has crashed...
$ python3 blah.py
Traceback (most recent call last):
File "blah.py", line 13, in ?
foo()
File "blah.py", line 10, in foo
bar()
File "blah.py", line 7, in bar
spam()
File "blah.py", 4, in spam
line x.append(3)
AttributeError: 'int' object has no attribute 'append'
Now what?!
The last line is the specific cause of the crash.
$ python3 blah.py
Traceback (most recent call last):
File "blah.py", line 13, in ?
foo()
File "blah.py", line 10, in foo
bar()
File "blah.py", line 7, in bar
spam()
File "blah.py", 4, in spam
line x.append(3)
## Cause of the crash
AttributeError: 'int' object has no attribute 'append'
However, it's not always easy to read or understand.
PRO TIP: Paste the whole traceback into Google.
Use the option -i
to keep Python alive when executing a script.
$ python3 -i blah.py
Traceback (most recent call last):
File "blah.py", line 13, in ?
foo()
File "blah.py", line 10, in foo
bar()
File "blah.py", line 7, in bar
spam()
File "blah.py", 4, in spam
line x.append(3)
AttributeError: 'int' object has no attribute 'append'
>>>
It preserves the interpreter state. That means that you can go poking around after the crash. Checking variable values and other state.
print()
debugging is quite common.
Tip: Make sure you use repr()
def spam(x):
print('DEBUG:', repr(x))
...
repr()
shows you an accurate representation of a value. Not the nice printing output.
>>> from decimal import Decimal
>>> x = Decimal('3.4')
## NO `repr`
>>> print(x)
3.4
## WITH `repr`
>>> print(repr(x))
Decimal('3.4')
>>>
You can manually launch the debugger inside a program.
def some_function():
...
breakpoint() ## Enter the debugger (Python 3.7+)
...
This starts the debugger at the breakpoint()
call.
In earlier Python versions, you did this. You'll sometimes see this mentioned in other debugging guides.
import pdb
...
pdb.set_trace() ## Instead of `breakpoint()`
...
You can also run an entire program under debugger.
$ python3 -m pdb someprogram.py
It will automatically enter the debugger before the first statement. Allowing you to set breakpoints and change the configuration.
Common debugger commands:
(Pdb) help ## Get help
(Pdb) w(here) ## Print stack trace
(Pdb) d(own) ## Move down one stack level
(Pdb) u(p) ## Move up one stack level
(Pdb) b(reak) loc ## Set a breakpoint
(Pdb) s(tep) ## Execute one instruction
(Pdb) c(ontinue) ## Continue execution
(Pdb) l(ist) ## List source code
(Pdb) a(rgs) ## Print args of current function
(Pdb) !statement ## Execute statement
For breakpoints location is one of the following.
(Pdb) b 45 ## Line 45 in current file
(Pdb) b file.py:45 ## Line 45 in file.py
(Pdb) b foo ## Function foo() in current file
(Pdb) b module.foo ## Function foo() in a module
It runs. Ship it!
Congratulations! You have completed the Debugging lab. You can practice more labs in LabEx to improve your skills.