A summary of several methods of Python code debugging

Source: Internet
Author: User
Tags readfile
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

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

[root@rcc-pok-idg-2255 ~]# 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 = "b BB "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

[root@rcc-pok-idg-2255 ~]# 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

[root@rcc-pok-idg-2255 ~]# 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: 
 
  
   
    (PDB) n  >/ROOT/EPDB1.P Y (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

[root@rcc-pok-idg-2255 ~]# 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

[root@rcc-pok-idg-2255 ~]# python epdb1.py  >/root/epdb1.py (4)? ()  b = "BBB" (PDB) List  1   import Pdb  2   a = "AAA" 3   pdb.set_trace ()  4 B = "BBB" 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

[root@rcc-pok-idg-2255 ~]# 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): # define S  Ubroutine 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" c = "CCC" (PDB) n >/root/epdb2.py (5) combine (), 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

[root@rcc-pok-idg-2255 ~]# 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, the download address is: 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 the thread  D  EF 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 the number of the "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, FileName):  file = open (filename) for line in  File.xreadlines ():   print line  try:  Thread.start_new_thread (Print_time, ("Thread-1", 2,))  Thread.start_new_thread (Check_sum, ("Thread-2", 4, 5,)) C21/>thread.start_new_thread (ReadFile, ("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

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

Ogging Lib consists of 4 main objects

  1. 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 ("").
  2. 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.
  3. 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.
  4. 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 I NFO for LOG1:B.C ')
Log1.error (' Error info to 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 Log1: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.

  • Related Article

    Contact Us

    The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

    If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.