【发布时间】:2019-01-09 01:37:29
【问题描述】:
调试 Python 的最佳技巧是什么?
请不要只列出特定的调试器而不说明它实际上可以做什么。
相关
【问题讨论】:
调试 Python 的最佳技巧是什么?
请不要只列出特定的调试器而不说明它实际上可以做什么。
【问题讨论】:
您可以使用 pdb 模块,在任何地方插入pdb.set_trace(),它将充当断点。
>>> import pdb
>>> a="a string"
>>> pdb.set_trace()
--Return--
> <stdin>(1)<module>()->None
(Pdb) p a
'a string'
(Pdb)
要继续执行,请使用c(或cont 或continue)。
可以使用 pdb 执行任意 Python 表达式。例如,如果发现错误,可以更正代码,然后键入类型表达式以在运行代码中产生相同的效果
ipdb 是 IPython 的 pdb 版本。它允许将 pdb 与所有 IPython 功能一起使用,包括制表符补全。
也可以在未捕获的异常上set pdb to automatically run。
Pydb 被编写为 Pdb 的增强版本。好处?
【讨论】:
myserver.com/pdb 添加一个视图,该视图仅执行 import pdb; pdb.set_trace()。如果您使用的是具有交互式调试器的 Flask/Werkzeug,您还可以拥有一个只执行 assert False 的视图。
http://pypi.python.org/pypi/pudb,一个全屏、基于控制台的 Python 调试器。
它的目标是在一个更轻量级和键盘友好的软件包中提供现代基于 GUI 的调试器的所有细节。 PuDB 允许您在终端中在您编写和测试代码的地方调试代码。如果您使用过基于 DOS 的优秀(但现在很古老)的 Turbo Pascal 或 C 工具,PuDB 的 UI 可能看起来很熟悉。
很适合调试独立脚本,只需运行
python -m pudb.run my-script.py
【讨论】:
pip install pudb安装
如果您使用 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
【讨论】:
记录
Python 已经拥有出色的 built-in logging module。您可能想使用logging template here。
日志记录模块让您指定重要程度;在调试期间,您可以记录所有内容,而在正常操作期间,您可能只记录关键内容。您可以关闭和打开设备。
大多数人只是使用基本的打印语句进行调试,然后删除打印语句。最好将它们留在里面,但禁用它们;然后,当您遇到另一个错误时,您可以重新启用所有内容并查看您的日志。
这可能是调试需要快速执行操作的程序的最佳方法,例如需要在网络连接的另一端超时并消失之前做出响应的网络程序。您可能没有太多时间单步调试器;但你可以让你的代码运行,并记录所有内容,然后仔细研究日志并找出真正发生的事情。
编辑:模板的原始 URL 是: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
【讨论】:
可以打印Python lines are executed 的内容(感谢 Geo!)。这有任意数量的应用程序,例如,您可以对其进行修改以检查何时调用特定函数或添加类似 ## 之类的内容,使其仅跟踪特定行。
code.interact 带您进入交互式控制台
import code; code.interact(local=locals())
如果您希望能够轻松访问控制台历史记录,请查看:“Can I have a history mechanism like in the shell?”(必须向下查找)。
可以为interpreter 启用自动完成功能。
【讨论】:
ipdb 就像 pdb,具有 ipython 的厉害之处。
【讨论】:
print 声明
debug_print 函数而不是 print 以便于禁用pprint 模块对于复杂结构非常有用【讨论】:
调试脚本的明显方法
python -m pdb script.py
如果您不知道该脚本的确切位置
python -m pdb ``which <python-script-name>``
【讨论】:
PyDev
PyDev 有一个非常好的交互式调试器。它具有监视表达式、悬停评估、线程和堆栈列表以及(几乎)您期望从现代可视化调试器获得的所有常用功能。您甚至可以附加到正在运行的进程并进行远程调试。
不过,与其他可视化调试器一样,我发现它主要用于解决简单问题,或者在我尝试了所有其他方法后非常复杂的问题。我仍然负责大部分繁重的日志记录工作。
【讨论】:
如果您熟悉 Visual Studio,Python Tools for Visual Studio 就是您要找的。p>
【讨论】:
Winpdb 非常好,与它的名字相反,它完全是跨平台的。
它有一个非常好的基于提示的和 GUI 调试器,并且支持远程调试。
【讨论】:
在 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 一起使用,这是一个可靠的图形调试器。因为我知道你会问,它可以做我期望图形调试器做的所有事情:)
我使用来自nose.tools 的pdb,这样我就可以调试单元测试以及普通代码。
最后,F7 映射将打印回溯(类似于当异常冒泡到堆栈顶部时得到的那种)。我发现它真的很有用不止几次。
【讨论】:
为您的类定义有用的 repr() 方法(这样您就可以看到对象是什么)并使用 repr() 或 "%r" % (...) 或 "... {0!r}..".format(...) 在您的调试消息/日志中是恕我直言,高效调试的关键。
此外,其他答案中提到的调试器将使用 repr() 方法。
【讨论】:
从正在运行的 Python 应用程序获取堆栈跟踪
有几个技巧here。其中包括
【讨论】:
如果可能,我会在 emacs 中使用 M-x pdb 进行源代码级调试。
【讨论】:
Andreas Zeller 在 Udacity 上有一个名为“Software Debugging”的完整在线课程,其中包含有关调试的提示:
课程总结
在本课程中,您将学习如何系统地调试程序,如何 自动化调试过程并构建几个自动化的 Python 中的调试工具。
为什么要学习这门课程?
在本课程结束时,您将深入了解 系统调试,会知道如何自动化调试,并且会 已经在 Python 中构建了多个功能调试工具。
先决条件和要求
Udacity 级别的编程和 Python 基础知识 需要 CS101 或更高版本。面向对象的基本理解 编程很有帮助。
强烈推荐。
【讨论】:
如果您想要一种漂亮的图形方式以可读的方式打印调用堆栈,请查看此实用程序: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 添加到请求URL 的末尾即可激活分析器。
【讨论】: