link experiment
This commit is contained in:
147
Notes/08_Testing_debugging/03_Debugging.md
Normal file
147
Notes/08_Testing_debugging/03_Debugging.md
Normal file
@@ -0,0 +1,147 @@
|
||||
# 8.3 Debugging
|
||||
|
||||
### Debugging Tips
|
||||
|
||||
So, you're program has crashed...
|
||||
|
||||
```bash
|
||||
bash % 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?!
|
||||
|
||||
### Reading Tracebacks
|
||||
|
||||
The last line is the specific cause of the crash.
|
||||
|
||||
```bash
|
||||
bash % 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.*
|
||||
|
||||
### Using the REPL
|
||||
|
||||
Use the option `-i` to keep Python alive when executing a script.
|
||||
|
||||
```bash
|
||||
bash % 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.
|
||||
|
||||
### Debugging with Print
|
||||
|
||||
`print()` debugging is quite common.
|
||||
|
||||
*Tip: Make sure you use `repr()`*
|
||||
|
||||
```python
|
||||
def spam(x):
|
||||
print('DEBUG:', repr(x))
|
||||
...
|
||||
```
|
||||
|
||||
`repr()` shows you an accurate representation of a value. Not the *nice* printing output.
|
||||
|
||||
```python
|
||||
>>> from decimal import Decimal
|
||||
>>> x = Decimal('3.4')
|
||||
# NO `repr`
|
||||
>>> print(x)
|
||||
3.4
|
||||
# WITH `repr`
|
||||
>>> print(repr(x))
|
||||
Decimal('3.4')
|
||||
>>>
|
||||
```
|
||||
|
||||
### The Python Debugger
|
||||
|
||||
You can manually launch the debugger inside a program.
|
||||
|
||||
```python
|
||||
def some_function():
|
||||
...
|
||||
breakpoint() # Enter the debugger (Python 3.7+)
|
||||
...
|
||||
```
|
||||
|
||||
This starts the debugger at the `breakpoint()` call.
|
||||
For earlier Python versions:
|
||||
|
||||
```python
|
||||
import pdb
|
||||
...
|
||||
pdb.set_trace() # Instead of `breakpoint()`
|
||||
...
|
||||
```
|
||||
|
||||
### Run under debugger
|
||||
|
||||
You can also run an entire program under debugger.
|
||||
|
||||
```bash
|
||||
bash % 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:
|
||||
|
||||
```code
|
||||
(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.
|
||||
|
||||
```code
|
||||
(Pdb) b 45 # Line 45 in current file
|
||||
(Pdb) b file.py:45 # Line 34 in file.py
|
||||
(Pdb) b foo # Function foo() in current file
|
||||
(Pdb) b module.foo # Function foo() in a module
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user