|
5 | 5 | ----------
|
6 | 6 | 问题
|
7 | 7 | ----------
|
8 |
| -Your program is broken and you’d like some simple strategies for debugging it. |
| 8 | +你的程序奔溃后该怎样去调试它? |
9 | 9 |
|
10 | 10 | |
|
11 | 11 |
|
12 | 12 | ----------
|
13 | 13 | 解决方案
|
14 | 14 | ----------
|
15 |
| -If your program is crashing with an exception, running your program as python3 -i |
16 |
| -someprogram.py can be a useful tool for simply looking around. The -i option starts |
17 |
| -an interactive shell as soon as a program terminates. From there, you can explore the |
18 |
| -environment. For example, suppose you have this code: |
| 15 | +如果你的程序因为某个异常而奔溃,运行 ``python3 -i someprogram.py`` 可执行简单的调试。 |
| 16 | +``-i`` 选项可让程序结束后打开一个交互式shell。 |
| 17 | +然后你就能查看环境,例如,假设你有下面的代码: |
19 | 18 |
|
20 |
| -# sample.py |
| 19 | +.. code-block:: python |
21 | 20 |
|
22 |
| -def func(n): |
23 |
| - return n + 10 |
| 21 | + # sample.py |
24 | 22 |
|
25 |
| -func('Hello') |
| 23 | + def func(n): |
| 24 | + return n + 10 |
26 | 25 |
|
27 |
| -Running python3 -i produces the following: |
28 |
| - |
29 |
| -bash % python3 -i sample.py |
30 |
| -Traceback (most recent call last): |
31 |
| - File "sample.py", line 6, in <module> |
32 | 26 | func('Hello')
|
33 |
| - File "sample.py", line 4, in func |
34 |
| - return n + 10 |
35 |
| -TypeError: Can't convert 'int' object to str implicitly |
36 |
| ->>> func(10) |
37 |
| -20 |
38 |
| ->>> |
39 |
| - |
40 |
| -If you don’t see anything obvious, a further step is to launch the Python debugger after |
41 |
| -a crash. For example: |
42 |
| - |
43 |
| ->>> import pdb |
44 |
| ->>> pdb.pm() |
45 |
| -> sample.py(4)func() |
46 |
| --> return n + 10 |
47 |
| -(Pdb) w |
48 |
| - sample.py(6)<module>() |
49 |
| --> func('Hello') |
50 |
| -> sample.py(4)func() |
51 |
| --> return n + 10 |
52 |
| -(Pdb) print n |
53 |
| -'Hello' |
54 |
| -(Pdb) q |
55 |
| ->>> |
56 |
| - |
57 |
| -If your code is deeply buried in an environment where it is difficult to obtain an inter‐ |
58 |
| -active shell (e.g., in a server), you can often catch errors and produce tracebacks yourself. |
59 |
| -For example: |
60 |
| - |
61 |
| -import traceback |
62 |
| -import sys |
63 |
| - |
64 |
| -try: |
65 |
| - func(arg) |
66 |
| -except: |
67 |
| - print('**** AN ERROR OCCURRED ****') |
68 |
| - traceback.print_exc(file=sys.stderr) |
69 |
| - |
70 |
| -If your program isn’t crashing, but it’s producing wrong answers or you’re mystified by |
71 |
| -how it works, there is often nothing wrong with just injecting a few print() calls in |
72 |
| -places of interest. However, if you’re going to do that, there are a few related techniques |
73 |
| -of interest. First, the traceback.print_stack() function will create a stack track of |
74 |
| -your program immediately at that point. For example: |
75 |
| - |
76 |
| ->>> def sample(n): |
77 |
| -... if n > 0: |
78 |
| -... sample(n-1) |
79 |
| -... else: |
80 |
| -... traceback.print_stack(file=sys.stderr) |
81 |
| -... |
82 |
| ->>> sample(5) |
83 |
| - File "<stdin>", line 1, in <module> |
84 |
| - File "<stdin>", line 3, in sample |
85 |
| - File "<stdin>", line 3, in sample |
86 |
| - File "<stdin>", line 3, in sample |
87 |
| - File "<stdin>", line 3, in sample |
88 |
| - File "<stdin>", line 3, in sample |
89 |
| - File "<stdin>", line 5, in sample |
90 |
| ->>> |
91 |
| - |
92 |
| -Alternatively, you can also manually launch the debugger at any point in your program |
93 |
| -using pdb.set_trace() like this: |
94 |
| - |
95 |
| -import pdb |
96 |
| - |
97 |
| -def func(arg): |
98 |
| - ... |
99 |
| - pdb.set_trace() |
| 27 | +
|
| 28 | +运行 ``python3 -i sample.py`` 会有类似如下的输出: |
| 29 | + |
| 30 | +:: |
| 31 | + |
| 32 | + bash % python3 -i sample.py |
| 33 | + Traceback (most recent call last): |
| 34 | + File "sample.py", line 6, in <module> |
| 35 | + func('Hello') |
| 36 | + File "sample.py", line 4, in func |
| 37 | + return n + 10 |
| 38 | + TypeError: Can't convert 'int' object to str implicitly |
| 39 | + >>> func(10) |
| 40 | + 20 |
| 41 | + >>> |
| 42 | + |
| 43 | +如果你看不到上面这样的,可以在程序奔溃后打开Python的调试器。例如: |
| 44 | + |
| 45 | +:: |
| 46 | + |
| 47 | + >>> import pdb |
| 48 | + >>> pdb.pm() |
| 49 | + > sample.py(4)func() |
| 50 | + -> return n + 10 |
| 51 | + (Pdb) w |
| 52 | + sample.py(6)<module>() |
| 53 | + -> func('Hello') |
| 54 | + > sample.py(4)func() |
| 55 | + -> return n + 10 |
| 56 | + (Pdb) print n |
| 57 | + 'Hello' |
| 58 | + (Pdb) q |
| 59 | + >>> |
| 60 | + |
| 61 | +如果你的代码所在的环境很难获取交互shell(比如在某个服务器上面), |
| 62 | +通常可以捕获异常后自己打印跟踪信息。例如: |
| 63 | + |
| 64 | +.. code-block:: python |
| 65 | +
|
| 66 | + import traceback |
| 67 | + import sys |
| 68 | +
|
| 69 | + try: |
| 70 | + func(arg) |
| 71 | + except: |
| 72 | + print('**** AN ERROR OCCURRED ****') |
| 73 | + traceback.print_exc(file=sys.stderr) |
| 74 | +
|
| 75 | +要是你的程序没有奔溃,而只是产生了一些你看不懂的结果, |
| 76 | +你在感兴趣的地方插入一下 ``print()`` 语句也是个不错的选择。 |
| 77 | +不过,要是你打算这样做,有一些小技巧可以帮助你。 |
| 78 | +首先,``traceback.print_stack()`` 函数会你程序运行到那个点的时候创建一个跟踪栈。例如: |
| 79 | + |
| 80 | +:: |
| 81 | + |
| 82 | + >>> def sample(n): |
| 83 | + ... if n > 0: |
| 84 | + ... sample(n-1) |
| 85 | + ... else: |
| 86 | + ... traceback.print_stack(file=sys.stderr) |
100 | 87 | ...
|
| 88 | + >>> sample(5) |
| 89 | + File "<stdin>", line 1, in <module> |
| 90 | + File "<stdin>", line 3, in sample |
| 91 | + File "<stdin>", line 3, in sample |
| 92 | + File "<stdin>", line 3, in sample |
| 93 | + File "<stdin>", line 3, in sample |
| 94 | + File "<stdin>", line 3, in sample |
| 95 | + File "<stdin>", line 5, in sample |
| 96 | + >>> |
| 97 | + |
| 98 | +另外,你还可以像下面这样使用 ``pdb.set_trace()`` 在任何地方手动的启动调试器: |
| 99 | + |
| 100 | +.. code-block:: python |
| 101 | +
|
| 102 | + import pdb |
101 | 103 |
|
102 |
| -This can be a useful technique for poking around in the internals of a large program |
103 |
| -and answering questions about the control flow or arguments to functions. For instance, |
104 |
| -once the debugger starts, you can inspect variables using print or type a command such |
105 |
| -as w to get the stack traceback. |
| 104 | + def func(arg): |
| 105 | + ... |
| 106 | + pdb.set_trace() |
| 107 | + ... |
| 108 | +
|
| 109 | +当程序比较大二你想调试控制流程以及函数参数的时候这个就比较有用了。 |
| 110 | +例如,一旦调试器开始运行,你就能够使用 ``print`` 来观测变量值或敲击某个命令比如 ``w`` 来获取追踪信息。 |
106 | 111 |
|
107 | 112 | |
|
108 | 113 |
|
109 | 114 | ----------
|
110 | 115 | 讨论
|
111 | 116 | ----------
|
112 |
| -Don’t make debugging more complicated than it needs to be. Simple errors can often |
113 |
| -be resolved by merely knowing how to read program tracebacks (e.g., the actual error |
114 |
| -is usually the last line of the traceback). Inserting a few selected print() functions in |
115 |
| -your code can also work well if you’re in the process of developing it and you simply |
116 |
| -want some diagnostics (just remember to remove the statements later). |
117 |
| -A common use of the debugger is to inspect variables inside a function that has crashed. |
118 |
| -Knowing how to enter the debugger after such a crash has occurred is a useful skill to |
119 |
| -know. |
120 |
| -Inserting statements such as pdb.set_trace() can be useful if you’re trying to unravel |
121 |
| -an extremely complicated program where the underlying control flow isn’t obvious. |
122 |
| -Essentially, the program will run until it hits the set_trace() call, at which point it will |
123 |
| -immediately enter the debugger. From there, you can try to make more sense of it. |
124 |
| -If you’re using an IDE for Python development, the IDE will typically provide its own |
125 |
| -debugging interface on top of or in place of pdb. Consult the manual for your IDE for |
126 |
| -more information. |
| 117 | +不要将调试弄的过于复杂化。一些简单的错误只需要观察程序堆栈信息就能知道了, |
| 118 | +实际的错误一般是堆栈的最后一行。 |
| 119 | +你在开发的时候,也可以在你需要调试的地方插入一下 ``print()`` |
| 120 | +函数来诊断信息(只需要最后发布的时候删除这些打印语句即可)。 |
| 121 | + |
| 122 | +调试器的一个常见用法是观测某个已经奔溃的函数中的变量。 |
| 123 | +知道怎样在函数奔溃后进入调试器是一个很有用的技能。 |
| 124 | + |
| 125 | +当你想解剖一个非常复杂的程序,底层的控制逻辑你不是很清楚的时候, |
| 126 | +插入 ``pdb.set_trace()`` 这样的语句就很有用了。 |
| 127 | + |
| 128 | +实际上,程序会一直运行到碰到 ``set_trace()`` 语句位置,然后立马进入调试器。 |
| 129 | +然后你就可以做更多的事了。 |
| 130 | + |
| 131 | +如果你使用IDE来做Python开发,通常IDE都会提供自己的调试器来替代pdb。 |
| 132 | +更多这方面的信息可以参考你使用的IDE手册。 |
0 commit comments