Reprinted from: http://www.ibm.com/developerworks/cn/linux/l-cn-pythondebugger/
Debug is a very important skill for any developer and it can help us pinpoint errors and find bugs in the program. Python offers a range of debug tools and packages that we can choose from. This article will mainly explain how to use the Python debug related tools for Debug.
debugging using the PDB
The PDB is a Python-brought package that provides an interactive source code debugging feature for Python programs, including setting breakpoints, stepping through debugging, entering function debugging, viewing current code, viewing stack fragments, dynamically changing the values of variables, and more. The PDB provides some common debugging commands, as detailed in table 1.
Table 1. PDB Common commands
thead>
command |
explanation |
break or B set breakpoint |
set breakpoint |
continue or C | td> continue executing program
list or L |
View Code snippet for current line |
step or S |
enter function |
return or R |
executes the code until it returns from the current function |
exit or Q |
abort and exit |
next or n |
execute next line |
pp |
Print variable value |
help |
help |
Here's a concrete example of how to debug with the PDB.
Listing 1. Test code example
Import pdb a = "AAA" Pdb.set_trace () b = "BBB" c = "CCC" final = a + B + C print final
Start debugging: Run the script directly, will stay at Pdb.set_trace (), select N+enter can perform the current statement. After you press N+enter for the first time, you can press ENTER directly to repeat the previous debug command.
Listing 2. Debug with PDB
[Email protected] ~]# python epdb1.py >/root/epdb1.py (4)? () b = "BBB" (PDB) n >/root/epdb1.py (5)? () c = "CCC" (PDB) >/root/epdb1.py (6)? Final = a + B + C (Pdb) List 1 import Pdb 2 a = "AAA" 3 pdb.set_trace () 4
b = "BBB" 5 C = "CCC" 6, final = a + B + C 7 print Final [EOF] (Pdb)
[eof] (Pdb) n >/root/epdb1.py (7)? () Print final (PDB)
Exit Debug: Use Quit or Q to exit the current debug, but quit quits the program in a very rude way, with the result of direct crash.
Listing 3. Exit Debug
[Email protected] ~]# python epdb1.py >/root/epdb1.py (4)? () b = "BBB" (PDB) n >/root/epdb1.py (5)? () c = "CCC" (PDB) Q Traceback (most recent call last): File "epdb1.py", line 5, in? c = "CCC" File "epdb1.py", line 5, in? c = "CCC" File "/usr/lib64/python2.4/bdb.py", line Trace_dispatch return Self.dispatch_line (frame) File "/usr/lib64/python2.4/bdb.py", line, Dispatch_line if Self.quitting:raise bdbquit bdb. Bdbquit
Print the value of the variable: if you need to print the value of a variable during debugging, you can use p plus the variable name directly, but be aware that printing only sees the actual value after the current statement has been executed, otherwise it will be reported Nameerror: < exceptions. Nameerror. ....> error.
Listing 4. Print variables during the debug process
[Email protected] ~]# python epdb1.py >/root/epdb1.py (4)? () b = "BBB" (PDB) n >/root/epdb1.py (5)? () c = "CCC" (PDB) P B ' BBB ' (PDB) ' BBB ' (PDB) n >/root/epdb1.py (6)? () Final = a + B + C (PDB) P C ' CCC ' (PDB) p final * * * nameerror: <exceptions. Nameerror instance at 0x1551b710 > (Pdb) n >/root/epdb1.py (7)? () Print final (PDB) p final ' AAABBBCCC ' (PDB)
Use C to stop the current debug so that the program continues execution. If you continue to have set_statement () in the following program, you re-enter the state of debug and the reader can add set_trace () validation before the code print final.
Listing 5. Stop debug to continue executing program
[Email protected] ~]# python epdb1.py >/root/epdb1.py (4)? () b = "BBB" (PDB) n >/root/epdb1.py (5)? () c = "CCC" (PDB) C AAABBBCCC
Display code: It is not always possible to remember the current block of code when debugging, if you want to see a specific block of code, you can display it by using the list or the L command. The list will point to the current debug statement with arrows.
Listing 6. Display code during debug
[Email protected] ~]# python epdb1.py >/root/epdb1.py (4)? () b = "BBB" (PDB) List 1 import Pdb 2 a = "AAA" 3 pdb.set_trace () 4 b = "BBB" C11/>5 C = "CCC" 6 final = a + B + C 7 pdb.set_trace () 8 Print Final [EOF] (PDB) C >/root/epdb1.py (8)? () Print final (Pdb) List 3 pdb.set_trace () 4 b = "BBB" 5 C = "CCC" 6 final = a + B + C 7 pdb.set_trace () 8, print final [EOF] (PDB)
Debug with a function
Listing 7. Examples of using functions
Import PDB def combine (s1,s2): # define subroutine Combine, which ... S3 = S1 + s2 + S1 # sandwiches S2 between copies of S1, ... S3 = ' "' + s3 + '" ' # encloses it in double quotes,... Return S3 # and returns it. A = "AAA" Pdb.set_trace () b = "BBB" c = "CCC" final = Combine (A, b) print final
If you use N for debug, the Final=combine (A, b) will be treated as a normal assignment statement and go to print final. What if you want to debug a function? You can use S to enter function blocks directly. The single-step debugging inside the function is similar to the one described above. If you do not want to step through the function, you can press R directly at the breakpoint to exit to the point where you called.
Listing 8. To debug a function
[[email protected] ~]# python epdb2.py >/root/epdb2.py (10)? () b = "BBB" (PDB) n >/root/epdb2.py (11)? () c = "CCC" (PDB) n >/root/epdb2.py (12)? ()-final = Combine (A, B) (Pdb) s--call-->/root/epdb2.py (3) combine () def combine (S1,S2): # Defin E subroutine combine, which ... (PDB) n >/root/epdb2.py (4) combine (), s3 = s1 + s2 + S1 # Sandwiches S2 between copies of S1, ... (PDB) List 1 Import Pdb 2 3 def Combine (S1,S2): # define subroutine Combine, which ... 4-s3 = S1 + s2 + S1 # Sandwiches S2 between copies of S1, ... 5 s3 = ' "' + s3 + '" ' # encloses it in double quotes,... 6 return S3 # and returns it. 7 8 A = "AAA" 9 pdb.set_trace () b = "BBB" one-by-one C = "CCC" (PDB) n >/root/epdb2.py (5) combine ()-& Gt S3 = ' "' + s3 + '" ' # encloses it in double quotes,... (PDB) n >/root/epdb2.py (6) combine (), return S3 # And returns it. (PDB) n--return-->/root/epdb2.py (6) combine (), "Aaabbbaaa", Return S3 # and returns it. (PDB) n >/root/epdb2.py (13)? (), Print final (Pdb)
Dynamically change the value while debugging. When debugging, you can dynamically change the value of variables, such as the following example. Note that there is an error below because B is already assigned, and if you want to change the assignment of B, you should use it! B.
Listing 9. Dynamically changing values while debugging
[email protected] ~]# python epdb2.py >/root/epdb2.py () b = "BBB" (PDB) var = "1234" (PDB) b = "AVFE" * * * * "The specified object ' =" Avfe "' is not a function or are not f Ound along Sys.path. (PDB)!b= "AFDFD" (PDB)
The obvious drawback of PDB debugging is that it is not good enough to support multi-threading, remote debugging, and there is no more intuitive interface to display, and it is not suitable for large python projects. In larger Python projects, these debugging requirements are common, so you need to use more advanced debugging tools. The debugging methods for the Pycharm IDE are described next.
Using Pycharm for debugging
Pycharm is a Python IDE created by jetbrains with syntax highlighting, Project management, code jumps, smart tips, AutoComplete, Unit testing, versioning, and more, as well as the features of Django development and Google App Engine Support. Divided into individual standalone and commercial editions, license support is also available, and a free 30-day trial can be obtained. Trial version of the Pycharm can be downloaded on the official website, for: http://www.jetbrains.com/pycharm/download/index.html. Pycharm also provides a more perfect debugging function, support multi-threading, remote debugging, etc., can support breakpoint settings, single-step mode, expression evaluation, variable view and a series of functions. The Pycharm IDE's debug window is shown in Layout 1.
Figure 1. Pycharm IDE Window Layout
The following example describes how to use Pycharm for multi-threaded debugging. The code example used for the specific debugging is shown in Listing 10.
Listing 10. Pycharm Debugging Code Instances
__author__ = ' zhangying ' #!/usr/bin/python import thread import time # Define a function for T He thread def print_time (ThreadName, delay): Count = 0 While count < 5:count + = 1 print "%s :%s "% (ThreadName, Time.ctime (Time.time ())) def check_sum (THREADNAME,VALUEA,VALUEB): print" To calculate the sum of Result=sum (VALUEA,VALUEB) print "The result is", result; def sum (VALUEA,VALUEB): If Valuea >0 and Valueb>0:return valuea+valueb def readFile (ThreadName, Filena Me): File = open (filename) for line in File.xreadlines (): Print line Try:thread.start_new_thread (pr Int_time, ("Thread-1", 2,)) Thread.start_new_thread (Check_sum, ("Thread-2", 4,5,)) Thread.start_new_thread (R Eadfile, ("Thread-3", "test.txt",)) Except:print "error:unable to start Thread" while 1: # print "End" PASS
You usually need to set breakpoints before debugging, where breakpoints can be set at the expression of a loop or conditional judgment or a key point in a program. The way to set breakpoints is very simple: in the Code edit box, move the cursor to the line where you want to set the breakpoint, and then press Ctrl+f8 or choose Menu "Run", "Toggle lines break point", more directly by double-clicking the left edge of the code edit, You can see a small red dot (2) appears. When debugging starts, the code that is currently executing is directly displayed in blue. Three breakpoints are set in, and blue is highlighted as executing code.
Figure 2. Breakpoint Settings
Expression evaluation: During debugging Sometimes you need to trace the value of some expressions to discover problems in the program, PYCHARM support expression evaluation, you can select the expression, and then select "Run", "Evaluate expression", in the window that appears directly selected Evaluate can then be viewed.
Pychar also provides Variables and Watches windows, where the values of the specific variables involved in the debug step can be viewed directly in the variable column.
Figure 3. Variable view
If you want to dynamically monitor a variable, you can select the variable directly and add the menu "Run", "Add Watch" to the watches bar. When debugging is made to the statement where the variable is located, you can see the specific value of the variable directly in that window.
Figure 4. Monitoring variables
For multithreaded programming, there are usually multiple threads, and when a breakpoint that requires debug is set in the thread body of a different thread, it usually requires the IDE to be supported by a good multi-threaded debugging feature. Pycharm automatically generates a virtual thread with a Dummy name at the beginning of the main thread, each frame corresponding to its own debug frame. 5, a total of four threads in this example, where the main line generates into three threads, respectively, dummy-4,dummy-5,dummy-6. Where Dummy-4 corresponds to thread 1, the remainder corresponds to thread 2 and thread 3 respectively.
Figure 5. multithreaded windows
When debugging into the various threads of the sub-program, frame will automatically switch to its corresponding frame, the corresponding variable bar will also show the relevant variables corresponding to the process, 6, direct control of the debug button, such as Setp in,step over can be easily debugged.
Figure 6. Child thread Debugging
View a larger image.
Using PyDev for debugging
PyDev is an open source plugin that integrates easily with Eclipse, providing convenient and powerful debugging capabilities. As well as a good Python IDE also provides syntax error hints, source code editing assistant, Quick Outline, Globals Browser, Hierarchy View, run and other powerful features. Here's how to integrate PyDev and Eclipse. Before installing PyDev, you need to install Java 1.4 or later, Eclipse, and Python. Step one: Start Eclipse, find the help bar in the Eclipse menu bar, select Help > Install New Software, and select the Add button to add Ptdev's download site Http://pydev.org/up Dates After selecting PyDev, complete the remaining steps to install the PyDev.
Figure 7. Installing PyDev
After the installation is complete, you need to configure the Python interpreter, and in the Eclipse menu bar, choose Window > Preferences > Pydev > Interpreter–python. Python is installed under the C:\Python27 path. Click New, select the Python interpreter python.exe, open a window with many checkboxes, select the path you want to add to the system PYTHONPATH, and click OK.
Figure 8. Configure PyDev
After you have configured Pydev, you can click Next to create a Python project by choosing File > New > Project > Pydev >pydev Project in the Eclipse menu bar, which assumes p The Ython project has been created, and there is a script that needs to be debugged remote.py (as follows), which is a script that logs on to a remote machine to execute some commands, which need to pass in some parameters at run time, and the following details how to pass in the parameters during the debugging process.
Listing 11. Pydev Debugging Sample Code
#!/usr/bin/env python import os def telnetdo (Host=none, User=none, Pass=none, Command=none): #define a function import telnetlib, sys if not HOST: try: host = sys.argv[1] USER = sys.argv[2] PASS = sys.argv[3 ] command = sys.argv[4] except: print "Usage:remote.py host user pass COMMAND" return tn = telnetlib. Telnet () # try: tn.open (HOST) except: print "Cannot open HOST" return tn.read_until ("Login : ") tn.write (USER + ' \ n ') if pass: tn.read_until (" Password: ") tn.write (PASS + ' \ n ' ) Tn.write (COMMAND + ' \ n ') tn.write ("exit\n") tmp = Tn.read_all () tn.close () del tn return TMP If __name__ = = ' __main__ ': print telnetdo ()
In debugging, some conditions need to pass some parameters, before debugging needs to be configured to receive the required parameters, select the program to be debugged (in this case remote.py), the script in the process of debugging need to enter four parameters: Host,user,password and commands. Select the program you want to debug under the project directory in Eclipse, right-click, select "Debug as", "Debug Configurations", and select "Variables" in the Arguments tab page. This is shown in Figure 9 below.
Figure 9. Configuration variables
Select "Edit varuables" after the window "select Variable", the following window appears, select "New" in and enter the corresponding variable name and value in the popup window. It is important to note that there must be a space behind the value, otherwise all parameters will be read as the first parameter.
Figure 10. Adding concrete variables
Configure all parameters in sequence, then select the corresponding variable in the order in which you want the parameters to be installed in the Select Variable window. After the configuration is complete, the status is as shown in 11.
Figure 11. Complete the configuration
Choose Debug to Start debugging the program, debugging methods similar to the use of the built-in debugging capabilities of Eclipse, and support multi-threaded debug, there are many articles, readers can search for reading, or refer to the "Use Eclipse Platform for debugging" article.
Use the log function to achieve the purpose of debugging
Log information is a very useful way to debug during software development, especially in situations where large software development processes require a lot of people to collaborate. Developers are able to identify problems in the code by adding specific information in the code that can record the various events that are in the process of running the software. This information may include time, descriptive information, and specific contextual information when an error or exception occurs. The most primitive debug method is to locate the problem of the program by outputting some relevant information by embedding the print statement in the code. However, this method has a certain flaw, the normal program output and debug information mixed together, to analyze the difficulty, when the program debugging end no longer need to debug output, usually there is no easy way to print the information to screen out or locate the file. The logging module in Python is a convenient solution to these problems, it provides logging capabilities, divides the level of logger into five levels, which can be set by Logger.setlevel (LVL). The default level is warning.
Table 2. Level of Log
| Level
Usage Scenarios |
DEBUG |
Detailed information to use when tracking issues |
INFO |
The normal information |
WARNING |
Some unforeseen problems occur, or will occur, such as low disk space, but do not affect the operation of the program |
ERROR |
Some of the functions in the program are affected due to some serious problems |
CRITICAL |
A serious error, or the program itself cannot continue to run |
Logging Lib consists of 4 main objects
- Logger:logger is the interface for program information output. It is scattered in different code so that the program can log the appropriate information at run time and determine what information needs to be output and distribute the information to its associated handler, based on the logging level or filter set. Common methods are Logger.setlevel (), Logger.addhandler (), Logger.removehandler (), Logger.addfilter (), Logger.debug (), Logger.info (), logger.warning (), Logger.error (), GetLogger (), etc. Logger supports hierarchical inheritance relationships, and the name of a child logger is usually the way the parent logger.name. If you do not create an instance of logger, use the default root logger to get the root logger instance by Logging.getlogger () or Logging.getlogger ("").
- Handler:handler is used to process the output of information, which can be output to a console, file, or network. You can add handler to the Logger object through Logger.addhandler (), and the commonly used handler have Streamhandler and Filehandler classes. The Streamhandler sends an error message to the stream, and the Filehandler class is used to output the log information to the file, which is defined by the two handler in the Logging core module. Other hander are defined in the Logging.handles module, such as Httphandler,sockethandler.
- Formatter:formatter determines the format of the log information, which is defined using the form similar to% (< dictionary key >) s, such as '% (asctime) s-% (levelname) s-% (message ) s ', supported keys can be viewed in Python's own document LogRecord attributes.
- Filter:filter is used to determine what information needs to be output. Can be used by handler and logger, support hierarchical relations, such as if the filter is set to a name called A.B logger, then the logger and its sub-logger information will be output, such as A.B,A.B.C.
Listing 12. Log usage examples
Import Logging log1=logging.getlogger (' B.C ') log2=logging.getlogger (' d.e ') Filehandler = logging. Filehandler (' Test.log ', ' a ') formatter = logging. Formatter ('% (name) s% (asctime) s% (levelname) s% (message) s ') Filehandler.setformatter (Formatter) filter= Logging. Filter (' B ') Filehandler.addfilter (filter) Log1.addhandler (Filehandler) Log2.addhandler (Filehandler ) Log1.setlevel (logging.info) log2.setlevel (logging. Debug) Log1.debug (' It is a debug info for log1 ') log1.info (' Normal infor for Log1 ') log1.warning (' Warning info for LOG1:B.C ') log1.error ("Error info for LOG1:ABCD") log1.critical (' Critical info for Log1:not Worked ') log2.debug (' Debug info for log2 ') log2.info (' Normal info for log2 ') log2.warning (' Warning Info for log2 ') log2.error (' error:b.c ') log2.critical (' critical ')
The above example sets filter B, then B.C is a sub-logger of B, so the logger related log information will be output if the filter is satisfied, and other logger that do not meet the criteria (this is D.E) will be filtered out.
Listing 13. Output results
B.C 2011-11-25 11:07:29,733 Info normal infor for log1 B.C 2011-11-25 11:07:29,733 WARNING WARNING INFO for log1:b.c
B.C 2011-11-25 11:07:29,733 Error Error info for LOG1:ABCD B.C 2011-11-25 11:07:29,733 CRITICAL CRITICAL info for L Og1:not worked
The use of logging is very simple, and it is thread-safe, with the following examples of multithreading how to use logging for Debug.
Listing 14. Multithreading using logging
logging.conf [ loggers] keys=root,simpleexample [handlers] keys=consolehandler [formatters] Keys=simpleformatter [Logger_root] Level=debug Handlers=consolehandler [logger_simpleexample] level=debug handlers= Consolehandler qualname=simpleexample propagate=0 [Handler_consolehandler] class= " Streamhandler " level=debug formatter=simpleformatter args= (sys.stdout,) [Formatter_ Simpleformatter] format=% (asctime) s-% (name) s-% (levelname) s-% (message) s datefmt= code example: #!/usr/bin/python Import thread import time import logging import Logging.config Logging.config.fileConfig (' logging.conf ') # Create logger logger = Logging.getlogger (' simpleexample ') # Define A function for the thread def print_time (ThreadName, delay): logger.debug (' Thread 1 call print_t IME function Body ') count = 0 logger.debug (' count:%s ', count)
Summarize
This article introduces several different ways of debugging in Python, including the PDB module, debugging with PyDev and Eclipse integration, Pycharm and debug logging, hoping to give the relevant Python users a bit of reference. More information on Python debugger can be found in resources.
Reference Learning
- Refer to Tutorial python for official documentation of Python.
- Refer to the Python logging documentation for more information on logging usage.
- Find out more about our most popular articles and tutorials in the DeveloperWorks Linux zone for more reference materials for Linux developers, including beginners for Linux.
- Check out all Linux tips and Linux tutorials on the developerWorks.
- Stay tuned for DeveloperWorks technical activities and webcasts.
Discuss
- Refer to the Python Debugger blog for more information on Python Debug.
- Joining the DeveloperWorks Chinese community, the DeveloperWorks community is a professional social networking community for global IT professionals who can provide community functions such as blogs, bookmarks, wikis, groups, contacts, sharing, and collaboration.
- Join the IBM software download and technology Exchange Group to participate in online communication.
"Go" Python Code debugging Tips