Loading... <h2 style="text-align:center"> <strong>调试你的Python代码</strong><br /> </h2> <p> <span style="color:#FF9900">译自: http://howchoo.com/g/zgi2y2iwyze/debugging-your-python-code </span><br /> <span style="color:#FF9900">作者: Ashley </span><br /> <span style="font-size:12px;font-family:'Microsoft YaHei'"> 当你不得不更新别人的代码时,你有多少次陷入这样一种境地?如果你是一个开发团队的一员,那我猜一定多于你愿意的次数。 结果我们发现Python (和其他语言一样)提供了在这种情况下便利的debug特性。愿这份快速指南能使你的生活轻松些。</span> </p> <h2> <strong>1 一段糟糕的代码</strong><br /> </h2> <p><span style="font-family:'Microsoft YaHei';font-size:12px"> 出于本教程段目的让我们假设如下一段简单段程序。这段程序获取两个命令行参数以及加减操作。 (让我们假设用户输入的参数无误,因此无需处理异常)</span></p> <pre class="prettyprint lang-py">import sys def add(num1=0, num2=0): return int(num1) + int(num2) def sub(num1=0, num2=0): return int(num1) - int(num2) def main(): #Assuming our inputs are valid numbers print sys.argv addition = add(sys.argv[1], sys.argv[2]) print addition subtraction = sub(sys.argv[1], sys.argv[2]) print subtraction if __name__ == '__main__': main()</pre> <h2> <strong>2 加入pdb</strong><br /> </h2> <p> <span style="font-size:12px">Python自带了名为pdb的,基于交互的源码debug模块。<br /> 你需要已如下方式启用该模块。 </span> </p> <pre class="prettyprint lang-py">import pdb pdb.set_trace()</pre> <p> <span style="font-size:12px"> 加入断点(break points) 的示例程序:</span> </p> <pre class="prettyprint lang-py">import pdb import sys def add(num1=0, num2=0): return int(num1) + int(num2) def sub(num1=0, num2=0): return int(num1) - int(num2) def main(): #Assuming our inputs are valid numbers print sys.argv pdb.set_trace() # <-- Break point added here addition = add(sys.argv[1], sys.argv[2]) print addition subtraction = sub(sys.argv[1], sys.argv[2]) print subtraction if __name__ == '__main__': main()</pre> <p> <span style="font-family:Microsoft YaHei"> </span> </p> <pre class="prettyprint lang-py"># /Users/someuser/debugger.py(15)main() -> addition = add(sys.argv[1], sys.argv[2]) (Pdb)</pre> <p> <span style="font-family:'Microsoft YaHei';font-size:12px">我们会看到下次被执行的将是第15行。<br /> 程序在执行第15行前暂停了。<br /> 我们在这里有一些选择。。。让我们在接下来的步骤中展示其中一部分。</span> </p> <h2> <strong>4 下一行 -> n</strong><br /> </h2> <p> 在debugger提示符处 按”n” 会到下一行。 </p> <pre class="prettyprint lang-py">> /Users/someuser/debugger.py(14)main() -> addition = add(sys.argv[1], sys.argv[2]) (Pdb) n > /Users/someuser/debugger.py(15)main() -> print addition</pre> <p> <span style="font-family:'Microsoft YaHei';font-size:12px"> 这会执行当前行并准备好执行下一行。<br /> 我们虽然能够通过使用”n” 来一行行执行程序,但这样不是太有用。<br /> 你可能已经注意到了pdb实际上并没有进入add函数中。让我们在看看debugger的其他选项,使排错变得更有趣。 </span> </p> <p> <span style="font-family:'Microsoft YaHei';color:#FF9900;font-size:12px"><em> 注意:<br /> 另一个酷酷的特性是按回车键会执行你之前执行过的命令(本例中为”n”)。</em></span> </p> <h2> <strong>5 打印 ->p</strong><br /> </h2> <p> <span style="font-family:'Microsoft YaHei';font-size:12px">让我们再次开始debug吧!(既然我们没有任何程序会执行完。你可以敲击”c”使pdb跳至最后或者下一个断点(break point)</span><span style="font-size:12px"> </span> </p> <p> <span style="line-height:1.5"> </span> </p> <pre class="prettyprint lang-py">['debugger.py', '1', '2'] > /Users/someuser/debugger.py(14)main() -> addition = add(sys.argv[1], sys.argv[2]) (Pdb)</pre> <p> <span style="line-height:1.5;font-family:'Microsoft YaHei';font-size:12px">现在如果我们想知道sys.argv包含了哪些参数,我们可以这么干:</span> </p> <p> <span style="line-height:1.5"> </span> </p> <pre class="prettyprint lang-py">-> addition = add(sys.argv[1], sys.argv[2]) (Pdb) p sys.argv ['debugger.py', '1', '2'] (Pdb) p sys.argv[1] '1' (Pdb)</pre> <p><span style="font-family:'Microsoft YaHei';font-size:12px"> 这在检测变量实际存储的值时非常有用。<br /> 现在让我们进入add函数内部</span></p> <h2> <strong>6 进入函数 -> s</strong><br /> </h2> <p> <span style="font-size:12px">我们可以通过使用”s”来进入我们的addition函数。</span> </p> <pre class="prettyprint lang-py">(Pdb) s --Call-- > /Users/someuser/debugger.py(4)add() -> def add(num1=0, num2=0): (Pdb) n > /Users/someuser/debugger.py(5)add() -> return int(num1) + int(num2) (Pdb)</pre> <p><span style="font-family:'Microsoft YaHei';font-size:12px"> 这使我们来到了add函数的内部,现在我们能够在其中使用”n, p”以及其他操作了。<br /> 这时敲击”r”会跳转至所进入函数的返回语句处。(译注:再次敲击时会跳转至函数调用处)<br /> 这在你想快速跳转至方法结尾时很有用。</span></p> <h2> <strong>7 动态添加断点(break point) -> b</strong><br /> </h2> <p> <span style="font-family:'Microsoft YaHei';font-size:12px">我们在运行程序前通过pdb.set_trace()设置了断点(break point)<br /> 通常在debugger开始后,我们会想在一些特定的位置设置断点(break point)<br /> 好基友 “b” 登场。<br /> 让我们再次执行我们的程序</span> </p> <pre class="prettyprint lang-py">['debugger.py', '1', '2'] > /Users/someuser/debugger.py(15)main() -> addition = add(sys.argv[1], sys.argv[2]) (Pdb)</pre> <p><span style="font-size:12px">现在我在第18行设置一个断点(break point)。</span></p> <pre class="prettyprint lang-py">-> addition = add(sys.argv[1], sys.argv[2]) (Pdb) b 18 Breakpoint 1 at /Users/someuser/debugger.py:18 (Pdb) c We are in add-- 3 > /Users/someuser/debugger.py(18)main() -> print subtraction (Pdb) p subtraction -1 (Pdb)</pre> <p><span style="font-family:'Microsoft YaHei';font-size:12px">如我们所见,pdb直接跳至第18行并等待进一步指令。<br /> pdb也会给断点赋一个数字(本例中为数字1)。我们能够使用(原文为”user” 疑似笔误)<br /> enable/disable 断点(break point)数字再进一步执行中启用或关闭相对应的断点(break point)。</span></p> <h2> <strong>8 列表 -> l</strong><br /> </h2> <p> <span style="font-family:'Microsoft YaHei';font-size:12px">有时在debug的过程中,你会迷失于代码中。此时,你可以使用”l”来输出一个格式良好的摘要来告知你你身在何处。# 斟酌</span> </p> <pre class="prettyprint lang-py">['debugger.py', '1', '2'] > /Users/someuser/debugger.py(15)main() -> addition = add(sys.argv[1], sys.argv[2]) (Pdb) l 10 11 def main(): 12 #Assuming our inputs are valid numbers 13 print sys.argv 14 pdb.set_trace() # <-- Break point added here 15 -> addition = add(sys.argv[1], sys.argv[2]) 16 print addition 17 subtraction = sub(sys.argv[1], sys.argv[2]) 18 print subtraction </pre> <h2> <strong>9 给变量动态赋值</strong><br /> </h2> <p> <span style="font-family:'Microsoft YaHei';font-size:12px">在debug时,能给变量赋值也有助于排错。<br /> 假设:</span> </p> <pre class="prettyprint lang-py">['debugger.py', '1', '2'] > /Users/someuser/debugger.py(15)main() -> addition = add(sys.argv[1], sys.argv[2]) (Pdb) n We are in add-- > /Users/someuser/debugger.py(16)main() -> print addition (Pdb) p addition 3 #<--- addition here is 3 (Pdb) addition = 'this is now string' #<--- We changed the value of additon (Pdb) n this is now string #<--- Now when we print it we actually gets it as a string. that we just set above. > /Users/someuser/debugger.py(17)main() -> subtraction = sub(sys.argv[1], sys.argv[2])</pre> <p><span style="font-family:'Microsoft YaHei';font-size:12px">注意:<br /> 如果你想给像”n”这样的变量赋值(即同时也是pdb 命令),你需要这样做:</span></p> <pre class="prettyprint lang-py">(Pdb) !n=5 (Pdb) p n 5</pre> <h2> <strong>10 退出 -> q</strong><br /> </h2> <p> <span style="font-family:'Microsoft YaHei';font-size:12px">最后你可以通过”q”,在任何时刻退出。程序执行会被终止。</span> </p> <h2> <strong>11 扩展阅读</strong><br /> </h2> <p> <span style="font-family:'Microsoft YaHei';font-size:12px">本文仅仅触及pdb的表面。还有更多的文档在向你招手!<br /> 那些使用ipython的能够在ipdb中找到更好的debugger:tab补全,语法高亮以及其他酷酷的特性。<br /> 如果你有其他使用pdb的有趣方法请在下面评论<br /> 排错愉快!</span></p> 最后修改:2021 年 12 月 10 日 10 : 53 AM © 允许规范转载 赞赏 如果觉得我的文章对你有用,请随意赞赏 赞赏作者 支付宝微信