This article mainly introduces the debugging Python program code Several methods summary, the article code is based on the python2.x version, the need friend may refer to under
The probability that the program can be written and run at once is very small, basically not more than 1%. There are always a variety of bugs to fix. Some bugs are simple, look at the error message to know that some bugs are very complex, we need to know when the error, which variables are the correct value, which variable value is wrong, therefore, a set of debugging procedures to fix the bug.
The first method is simple, straightforward, and effective by printing the variables that might be problematic:
|1 2 3 4 5 6 7 8 9 10||# err.py def foo (s): n = Int (s) print ' >>> n =%d '% n return 10/n def main (): foo (' 0 ') main ()|
Find the printed variable value in the output after execution:
|1 2 3 4 5||$ python err.py >>> n = 0 Traceback (most recent call last): ... Zerodivisionerror:integer division or modulo by zero|
The biggest disadvantage with print is that the future has to delete it, think of the program everywhere is print, the results will also contain a lot of junk information. So, we have a second method.
Where print is used to assist in viewing, an assertion (assert) can be used instead:
|1 2 3 4 5 6 7 8||# err.py def foo (s): n = Int (s) assert n!= 0, ' n is zero! ' return 10/n def main (): foo (' 0 ')|
Assert means that the expression N!= 0 should be true, otherwise, the subsequent code will be wrong.
If the assertion fails, the Assert statement itself throws a Assertionerror:
|1 2 3 4||$ python err.py traceback (most recent call last): ... Assertionerror:n is zero!|
A program that is full of assert is no better than print. However, you can use the-o parameter to turn off the assert when you start the Python interpreter:
|1 2 3 4||$ python-o err.py Traceback (most recent call last): ... Zerodivisionerror:integer division or modulo by zero|
After closing, you can look at all assert statements as pass.
Replacing print with logging is the 3rd way, and the assert ratio, logging does not throw an error, and can be exported to a file:
|1 2 3 4 5 6 7||# err.py Import Logging s = ' 0 ' n = Int (s) logging.info (' n =%d '% n) print 10/n|
Logging.info () Can output a paragraph of text. Run, and found no information except Zerodivisionerror. What's going on?
Don't worry, add a row after import logging and try again:
|1 2||Import Logging Logging.basicconfig (Level=logging.info)|
See the output:
|1 2 3 4 5 6||$ python err.py info:root:n = 0 Traceback (most recent call last): File "err.py", line 8, in <module> print 10/n Z Erodivisionerror:integer division or modulo by zero|
This is the benefit of logging, which allows you to specify the level of logging information, there are several levels of debug,info,warning,error, and when we specify Level=info, Logging.debug does not work. Similarly, after specifying level=warning, debug and info will not work. In this way, you can safely output different levels of information, do not delete, and finally unified control of the output level of information.
Another benefit of logging is that with simple configuration, a single statement can be exported to different places, such as console and file.
The 4th way is to start the Python debugger pdb, let the program run in one step, and view the running state at any time. Let's get the program ready:
|1 2 3 4||# err.py s = ' 0 ' n = Int (s) Print 10/n|
And then start:
|1 2 3||$ python-m pdb err.py >/users/michael/github/sicp/err.py (2) <module> ()-> s = ' 0 '|
After starting with the parameter-m PDB, the PDB navigates to the next code to be executed-> s = ' 0 '. Enter command l to view the code:
|1 2 3 4 5 6||(PDB) L 1 # err.py 2-> s = ' 0 ' 3 n = Int (s) 4 print 10/n [EOF]|
Enter command N to step through the code:
|1 2 3 4 5 6||(PDB) n >/users/michael/github/sicp/err.py (3) <module> ()-> n = Int (s) (PDB) n >/users/michael/github/sic p/err.py (4) <module> ()-> print 10/n|
You can enter the command p variable name at any time to view the variable:
|1 2 3 4||(PDB) p s ' 0 ' (PDB) p N 0|
Enter command Q to finish debugging and exit the program:
|1 2 3 4 5||(PDB) n zerodivisionerror: ' integer division or modulo by zero ' >/users/michael/github/sicp/err.py (4) <module> ( )-> print 10/n (Pdb) Q|
This method of debugging on the command line through the PDB is theoretically omnipotent, but it is too much trouble, and if there are 1000 lines of code, how many commands to run to line No. 999? Fortunately, we have another debugging method.
This method is also in the PDB, but does not require stepping, we only need to import the PDB, and then, where possible error place a pdb.set_trace (), you can set a breakpoint:
|1 2 3 4 5 6 7||# err.py Import pdb s = ' 0 ' n = Int (s) pdb.set_trace () # Running here automatically pauses the print 10/n|
Run the code, the program automatically pauses in Pdb.set_trace () and enters the PDB debugging environment, you can view the variable with the command p, or continue running with command C:
|1 2 3 4 5 6 7 8 9 10||$ python err.py >/users/michael/github/sicp/err.py (7) <module> ()-> print 10/n (PDB) p N 0 (PDB) C Traceback (most recent call last): File "err.py", line 7, in <module> print 10/n Zerodivisionerror:integer division or MoD Ulo by Zero|
This approach is much higher than the direct start of the PDB single step debugging, but it is not high enough.
If you want to set breakpoints and step by bit, you need an IDE that supports debugging. Now the better Python IDE has pycharm:
In addition, Eclipse plus the Pydev plug-in can also debug Python programs.
The most painful thing to write a program is debugging, the program will often be your unexpected process to run, you expect to execute the statement is not actually executed at this time, you need to debug.
Although it is convenient to debug with the IDE, in the end you will find that logging is the ultimate weapon.