Python调试技巧

时间:2009-10-26 04:16:40

标签: python debugging

调试Python的最佳技巧是什么?

请不要只列出特定的调试器而不说它实际可以做什么。

相关

18 个答案:

答案 0 :(得分:139)

<强> PDB

你可以使用pdb模块,在任何地方插入pdb.set_trace(),它将作为一个断点。

>>> import pdb
>>> a="a string"
>>> pdb.set_trace()
--Return--
> <stdin>(1)<module>()->None
(Pdb) p a
'a string'
(Pdb)

要继续执行,请使用c(或contcontinue)。

可以使用pdb执行任意Python表达式。例如,如果发现错误,可以更正代码,然后键入类型表达式以在运行代码中具有相同的效果

ipdb是IPython的pdb版本。它允许使用pdb和所有IPython功能,包括选项卡完成。

对未捕获的异常也可以set pdb to automatically run

Pydb被编写为Pdb的增强版本。优点

答案 1 :(得分:78)

http://pypi.python.org/pypi/pudb,一个基于控制台的全屏Python调试器。

  

它的目标是在更轻量级和键盘友好的包中提供现代基于GUI的调试器的所有细节。 PuDB允许您在编写和测试它的位置调试代码 - 在终端中。如果您使用过基于DOS的Turbo Pascal或C工具,那么PuDB的用户界面可能看起来很熟悉。

pudb screenshot

很高兴调试独立脚本,只需运行

python -m pudb.run my-script.py

答案 2 :(得分:40)

如果您使用的是pdb,则可以为快捷方式定义别名。我用这些:

# Ned's .pdbrc

# Print a dictionary, sorted. %1 is the dict, %2 is the prefix for the names.
alias p_ for k in sorted(%1.keys()): print "%s%-15s= %-80.80s" % ("%2",k,repr(%1[k]))

# Print the instance variables of a thing.
alias pi p_ %1.__dict__ %1.

# Print the instance variables of self.
alias ps pi self

# Print the locals.
alias pl p_ locals() local:

# Next and list, and step and list.
alias nl n;;l
alias sl s;;l

# Short cuts for walking up and down the stack
alias uu u;;u
alias uuu u;;u;;u
alias uuuu u;;u;;u;;u
alias uuuuu u;;u;;u;;u;;u
alias dd d;;d
alias ddd d;;d;;d
alias dddd d;;d;;d;;d
alias ddddd d;;d;;d;;d;;d

答案 3 :(得分:33)

<强>登录

Python已经有了很好的 built-in logging module。您可能想要使用logging template here

日志记录模块可让您指定重要级别;在调试期间,您可以记录所有内容,而在正常操作期间,您可能只记录关键内容。你可以关闭和打开它。

大多数人只是使用基本的print语句进行调试,然后删除print语句。最好留下它们,但禁用它们;然后,当你有另一个bug时,你可以重新启用所有内容并查看你的日志。

这可能是调试需要快速执行的程序的最佳方法,例如需要在网络连接的另一端超时和消失之前响应的网络程序。您可能没有太多时间单步执行调试器;但你可以让你的代码运行,记录所有内容,然后查看日志并找出真正发生的事情。

编辑:模板的原始网址为:http://aymanh.com/python-debugging-techniques

此页面丢失,因此我将其替换为对archive.org保存的快照的引用:http://web.archive.org/web/20120819135307/http://aymanh.com/python-debugging-techniques

如果它再次消失,这里是我提到的模板。这是从博客中获取的代码;我没有写。

import logging
import optparse

LOGGING_LEVELS = {'critical': logging.CRITICAL,
                  'error': logging.ERROR,
                  'warning': logging.WARNING,
                  'info': logging.INFO,
                  'debug': logging.DEBUG}

def main():
  parser = optparse.OptionParser()
  parser.add_option('-l', '--logging-level', help='Logging level')
  parser.add_option('-f', '--logging-file', help='Logging file name')
  (options, args) = parser.parse_args()
  logging_level = LOGGING_LEVELS.get(options.logging_level, logging.NOTSET)
  logging.basicConfig(level=logging_level, filename=options.logging_file,
                      format='%(asctime)s %(levelname)s: %(message)s',
                      datefmt='%Y-%m-%d %H:%M:%S')

  # Your program goes here.
  # You can access command-line arguments using the args variable.

if __name__ == '__main__':
  main()

以下是他对如何使用上述内容的解释。再说一次,我没有得到这个功劳:


默认情况下,日志记录模块会打印关键,错误和警告消息。要更改此值以便打印所有级别,请使用:

$ ./your-program.py --logging=debug

要将日志消息发送到名为debug.log的文件,请使用:

$ ./your-program.py --logging-level=debug --logging-file=debug.log

答案 4 :(得分:20)

可以打印Python lines are executed(感谢Geo!)。这有任意数量的应用程序,例如,您可以修改它以检查何时调用特定函数或添加类似##的内容使其仅跟踪特定行。

code.interact带您进入交互式控制台

import code; code.interact(local=locals())

如果您希望能够轻松访问控制台历史记录,请查看:“Can I have a history mechanism like in the shell?”(将不得不向下看)。

可以为interpreter启用自动完成功能。

答案 5 :(得分:19)

ipdb就像pdb一样,具有ipython的绝佳性。

答案 6 :(得分:17)

print陈述

  • 有些人建议使用debug_print功能代替打印以便轻松停用
  • pprint模块对于复杂结构非常有用

答案 7 :(得分:16)

调试脚本的明显方法

python -m pdb script.py
  • 在该脚本引发异常时很有用
  • 在使用virtualenv和pdb命令时没有使用venvs python版本。

如果您不确切知道该脚本的位置

python -m pdb ``which <python-script-name>``

答案 8 :(得分:15)

<强>的PyDev

PyDev有一个非常好的交互式调试器。它具有监视表达,悬停评估,线程和堆栈列表以及(几乎)所有您希望从现代可视化调试器中获得的常用设施。您甚至可以连接到正在运行的进程并进行远程调试。

与其他可视调试器一样,我发现它主要用于简单的问题,或者在我尝试了其他所有问题之后用于非常复杂的问题。我仍然使用伐木来完成大部分繁重的工作。

答案 9 :(得分:15)

如果您熟悉Visual Studio,Python Tools for Visual Studio就是您所寻找的。

enter image description here

答案 10 :(得分:12)

Winpdb非常好,与其名称相反,它完全是跨平台的。

它有一个非常好的基于提示的 GUI调试器,并支持远程调试。

答案 11 :(得分:7)

在Vim中,我有这三种绑定:

map <F9> Oimport rpdb2; rpdb2.start_embedded_debugger("asdf") #BREAK<esc>
map <F8> Ofrom nose.tools import set_trace; set_trace() #BREAK<esc>
map <F7> Oimport traceback, sys; traceback.print_exception(*sys.exc_info()) #TRACEBACK<esc>

rpdb2是一个远程Python调试器,可以与WinPDB一起使用,WinPDB是一个可靠的图形化调试器。因为我知道你会问,它可以做我希望图形调试器做的所有事情:)

我使用pdb中的nose.tools,以便我可以调试单元测试以及普通代码。

最后,F7映射将打印回溯(类似于异常气泡到堆栈顶部时获得的那种)。我发现它确实有用了几次。

答案 12 :(得分:4)

为您的类定义有用的 repr ()方法(以便您可以查看对象是什么)并使用repr()或“%r”%(...)或“...调试消息/日志中的{0!r} ..“。format(...)是IMHO高效调试的关键。

此外,其他答案中提到的调试器将使用 repr ()方法。

答案 13 :(得分:2)

从正在运行的Python应用程序获取堆栈跟踪

有几个技巧here。其中包括

  • 通过发送信号打破解释器/打印堆栈跟踪
  • 从无准备的Python进程中获取堆栈跟踪
  • 使用标志运行解释器以使其对调试很有用

答案 14 :(得分:2)

如果您不喜欢在调试器中花费时间(并且不喜欢pdb命令行界面的可用性差),您可以转储执行trace并在以后进行分析。例如:

python -m trace -t setup.py install > execution.log

这会将setup.py install执行的所有源代码行转储到execution.log

为了更容易自定义跟踪输出并编写自己的跟踪器,我将一些代码放在xtrace模块(公共域)中。

答案 15 :(得分:1)

如果可能,我使用emacs中的M-x pdb进行调试以进行源代码级调试。

答案 16 :(得分:1)

有一个完整的在线课程,名为&#34; Software Debugging&#34;作者:Andreas Zeller关于Udacity的文章,其中包含有关调试的提示:

  

课程摘要

     

在本课程中,您将学习如何系统地调试程序,如何   自动化调试过程并构建几个自动化   Python中的调试工具。

     

为什么选择此课程?

     

在本课程结束时,您将对此有充分的了解   系统调试,将知道如何自动化调试和将   已经在Python中构建了几个功能调试工具。

     

先决条件和要求

     

Udacity级别的编程和Python的基础知识   需要CS101或更高版本。对面向对象的基本理解   编程很有帮助。

强烈推荐。

答案 17 :(得分:0)

如果你想以一种漂亮的图形方式以可读的方式打印调用堆栈,请查看此实用程序:https://github.com/joerick/pyinstrument

从命令行运行:

python -m pyinstrument myscript.py [args...]

作为模块运行:

from pyinstrument import Profiler

profiler = Profiler()
profiler.start()

# code you want to profile

profiler.stop()
print(profiler.output_text(unicode=True, color=True))

使用django运行:

只需将pyinstrument.middleware.ProfilerMiddleware添加到MIDDLEWARE_CLASSES,然后将?profile添加到请求网址的末尾即可激活分析器。