PYTHON code, especially code written by someone else, doesn't understand. What to do? In fact Python also provides a similar to the C language for debug gdb. It's called the PDB. Combined with my own study, a simple example, to do memo and compensatory learning.
First, reference:
1, Http://web.stanford.edu/class/physics91si/2013/handouts/Pdb_Commands.pdf
2, https://docs.python.org/2/library/pdb.html
Use Shadowsocks's local.py code as an example to demonstrate the corresponding basic command.
local.py Code:
#!/usr/bin/env python# -*- coding: utf-8 -*-## copyright 2012-2015 clowwindy## licensed under the apache license, version 2.0 (the " License "); you may# not use this file except in compliance With the license. you may obtain# a copy of the license at## http://www.apache.org/licenses/license-2.0## unless required by applicable law or agreed to in writing, software# distributed under the license is distributed on an "AS IS" basis, without# warranties or conditions of any kind, either Express or implied. see the# license for the specific language governing permissions&Nbsp;and limitations# under the license.from __future__ import absolute_ Import, division, print_function, with_statementimport sysimport osimport loggingimport signalsys.path.insert (0, os.path.join (Os.path.dirname (__file__), '. /')) From shadowsocks import shell, daemon, eventloop, tcprelay, udprelay, asyncdnsdef main (): shell.check_python () # fix py2exe if hasattr (sys, "Frozen") and sys.frozen in ("Windows_exe", "Console_exe"): p = os.path.dirname (Os.path.abspath (sys.executable)) os.chdir (P) config = Shell.get_config (True) daemon.daemon_exec (config) try: logging.info ("starting local at %s:%d" % (config[' Local _address '], config[' Local_port ')) dns_resolver = asyncdns. Dnsresolver () tcp_server = tcprelay. Tcprelay (config, dns_resolver, true) udp_server = udprelay. Udprelay (config, dns_resolver, true) loop = eventloop. EventLoop () dns_resolver.add_to_loop (loop) tcp_server.add_to_loop (Loop) Udp_server.add_to_loop (Loop) def handler (signum, _): logging.warn (' Received SIGQUIT, doing graceful shutting down.. ') tcp_server.close (next_tick=True) udp_server.close (next_tick=True) signal.signal (GetAttr (signal, ' sigquit ', signal. SIGTERM), handler) def int_handler (signum, _): sys.exit (1) signal.signal (signal. Sigint, int_handler) daemon.set_user (config.get (' user ', none)) &Nbsp; loop.run () except Exception as e: shell.print_exception (E) sys.exit (1) if __name__ == ' __main__ ': main ()
To match the test, write a fake profile Config.json:
{"Server": "127.0j.0.1", "Server_port": 8388, "Local_port": 10808, "password": "Bgt56yhn", "Timeout": 600, " Method ": null}
I. How to debug and get help using the PDB
1. When the script starts, it loads the PDB debug information
python-m pdb ScriptFile [ARG] #此中情况, the program sets a breakpoint on the first line of the code
2. Change script to add PDB debug information
Import Pdbpdb.set_trace () # Set a breakpoint somewhere in the program
OK, we are here for simple diagram, do not change the local.py source code, directly using the first method to debug
$ python -m pdb local.py -c config.json> /home/test/python/ shadowsocks/shadowsocks/local.py (+) <module> ()-> from __future__ import absolute_ import, division, print_function, (Pdb) helpDocumented commands (type help <topic>):========================================eof bt cont enable jump Pp run unt a c continue exit l q s until alias cl d h list quit step up args clear debug help n r tbreak w b commands disable ignore next restart u whatisbreak condition down j p return unalias where miscellaneous help topics:==========================exec pdbundocumented commands:======================retval rv
As can be seen from the above results, the default code of the first behavior breakpoint (just a false breakpoint, the Display breakpoint command is not visible), the program stays here.
In the PDB state, use the Help directive to obtain the PDB's assistance.
Second, n (next)
When n (next) is entered, the next line of code can be executed.
(PDB) n>/home/test/python/shadowsocks/shadowsocks/local.py <module> () import sys (PDB) n>/home/ test/python/shadowsocks/shadowsocks/local.py (<module>), import OS (Pdb) n>/home/test/python/ shadowsocks/shadowsocks/local.py (<module>), Import logging (Pdb) # Here is a blank, press a enter >/HOME/TEST/PYT hon/shadowsocks/shadowsocks/local.py (<module>), import Signal (PDB) # Here is a blank, press a enter >/home/test/p ython/shadowsocks/shadowsocks/local.py (+) <module> () sys.path.insert (0, Os.path.join (os.path.dirname ( __file__), '. /')) (PDB)
Attention:
A very bull feature is that you can click the ENTER key to execute the previous command (the command executed in the example above is N).
Third, S (step), B (Break) and C (continue) directives
s (step) input, you can enter the relevant function in this line of code to execute
When B num is entered, a breakpoint is set on a line (num). If you enter B directly, all breakpoints are displayed
Originally, intended to talk about the s (step) instruction and the n (next) instructions put together, make a comparison. But I feel more like the S (step) directive should be combined with B (break) and C (continue) to make it feel more efficient.
To actually speak, I want to hit a breakpoint on the main () function, then go straight to the breakpoint and finally enter the main function.
The premise is, I know the main () function is in line 72 (which line of the function is in the file, this is on its own)
> /home/test/python/shadowsocks/shadowsocks/local.py (+) <module> ()-> from __future_ _ import absolute_import, division, print_function, (PDB) b 72 # set a breakpoint on the 72 line breakpoint 1 at /home/test/python/shadowsocks/ shadowsocks/local.py:72 (PDB) b # Show All Breakpoints Num type Disp Enb Where1 breakpoint keep yes at /home/test/python/shadowsocks/shadowsocks/ local.py:72 (Pdb) c # go straight to this breakpoint > /home/test/ python/shadowsocks/shadowsocks/local.py <module> ()-> main () (PDB) s # s , enter the main function--call--> /home/dexin/python/shadowsocks/ shadowsocks/local.py (+) Main ()-> def main ():(Pdb) l 25 26 sys.path.insert (0, os.path.join (Os.path.dirname (__file__), ' ... /')) 27 from shadowsocks import shell, daemon, eventloop, tcprelay, udprelay, asyncdns 28 29 30 -> def main (): 31 shell.check_python () 32 33 # fix py2exe 34 if hasattr (sys, "Frozen") and sys.frozen in 35 ("Windows_exe", "Console_exe"):(Pdb) n # n moves to the next line > /home/dexin/python/shadowsocks/shadowsocks/local.py () main ()-> shell.check_ Python () (Pdb) s # s go to check_python function--call--> /home/dexin/python/shadowsocks/shadowsocks/shell.py (+) Check_python ()-> def check_python ():(Pdb)
In the above debugging, the use of the L (list) instruction, the meaning of this command is to display the code. The default is not what parameters are in the case.
Displays a total of 11 lines of code up and down the current line.
Clear Num Clears the previously set breakpoint, where Num is the meaning of the first breakpoint
(PDB) &NBSP;B&NBSP;34BREAKPOINT&NBSP;1&NBSP;AT&NBSP;/HOME/TEST/PYTHON/SHADOWSOCKS/SHADOWSOCKS/LOCAL.PY:34 (PDB) bNum Type Disp Enb where1 breakpoint keep yes at /home/test/python/ Shadowsocks/shadowsocks/local.py:34 (PDB) l 36 p = os.path.dirname (Os.path.abspath (sys.executable)) 37 os.chdir (P) 38 39 config = shell.get_config (True) 40 41 daemon.daemon_exec (config) 42 43 try: 44 logging.info ("starting local at %s:%d" % 45 (config[' local_address '], config[' Local_port ')) 46 (PDB) b 41breakpoint 2 at /home/dexin/python/shadowsocks/ Shadowsocks/local.py:41 (PDB) b # Show all Breakpoints num Type Disp Enb Where1 breakpoint keep yes at /home/dexin/python/shadowsocks/ shadowsocks/local.py:342 breakpoint keep yes at / Home/dexin/python/shadowsocks/shAdowsocks/local.py:41 (PDB) clear 1 # Clear First breakpoint Deleted breakpoint 1 (PDB) bNum Type Disp Enb where2 breakpoint keep yes at /home/ Dexin/python/shadowsocks/shadowsocks/local.py:41 (PDB)
V, p (print) printing
The function of this instruction is mainly used to print the variable values in the program.
(Pdb) n> /home/test/python/shadowsocks/shadowsocks/shell.py (PNS) Check_python ()-> if Info[0] == 2 and not info[1] >= 6: (Pdb) l 32 verbose = 0 33 34 35 def check_python (): 36 info = sys.version_info 37 -> &NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;IF&NBSP;INFO[0]&NBSP;==&NBSP;2&NBSP;AND&NBSP;NOT&NBSP;INFO[1] >= 6: 38 print (' python 2.6+ required ') 39 sys.exit (1) 40 elif info[0] == 3 and not info[1] >= 3: 41 print (' python 3.3+ required ') 42 sys.exit (1) (PDB) p info # Print Variable value sys.version_info (major=2, minor=7, micro=6, releaselevel= ' final ', serial=0)
Vi. dynamic adjustment of variable values
(Pdb) n> /home/test/python/shadowsocks/shadowsocks/shell.py (PNS) Check_python ()-> if Info[0] == 2 and not info[1] >= 6: (Pdb) l 32 verbose = 0 33 34 35 def check_python (): 36 info = sys.version_info 37 -> &NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;IF&NBSP;INFO[0]&NBSP;==&NBSP;2&NBSP;AND&NBSP;NOT&NBSP;INFO[1] >= 6: 38 print (' python 2.6+ required ') 39 sys.exit (1) 40 elif info[0] == 3 and not info[1] >= 3: 41 print (' python 3.3+ required ') 42 sys.exit (1) (PDB) p infosys.version_info ( Major=2, minor=7, micro=6, releaselevel= ' final ', serial=0) (Pdb) info = ( 11,22,33) (Pdb) p info (11, 22, 33)
Seven, Q (quit) exit
(PDB) quit
This article is from the "Learning Notes" blog, so be sure to keep this source http://unixman.blog.51cto.com/10163040/1663867
The PDB module in Python