Python调试技巧

Python调试技巧,python,debugging,Python,Debugging,调试Python的最佳技巧是什么 请不要只列出一个特定的调试器,而不说它实际上可以做什么 相关的 -这讨论了最小化错误 打印语句 有些人建议使用debug\u print功能而不是print,以方便禁用 pprint模块对于复杂结构非常有用 您可以使用pdb模块,在任意位置插入pdb.set_trace(),它将用作断点 >>> import pdb >>> a="a string" >>> pdb.set_trace() --Retu

调试Python的最佳技巧是什么

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

相关的
  • -这讨论了最小化错误

打印
语句

  • 有些人建议使用
    debug\u print
    功能而不是print,以方便禁用
  • pprint
    模块对于复杂结构非常有用
    • 您可以使用pdb模块,在任意位置插入
      pdb.set_trace()
      ,它将用作断点

      >>> import pdb
      >>> a="a string"
      >>> pdb.set_trace()
      --Return--
      > <stdin>(1)<module>()->None
      (Pdb) p a
      'a string'
      (Pdb)
      
      导入pdb >>>a=“字符串” >>>pdb.set_trace() --返回-- >(1)无 (Pdb)p a “一串” (Pdb) 要继续执行,请使用
      c
      (或
      cont
      continue

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

      ipdb是pdb的一个版本。它允许pdb与所有IPython功能一起使用,包括制表符完成

      也可以在未捕获的异常上进行修改


      已编写为Pdb的增强版本。好处?

      ipdb就像pdb一样,有着ipython的惊人之处。

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

      code.interact将您带入一个交互式控制台

      import code; code.interact(local=locals())
      
      如果您希望能够轻松访问控制台历史记录,请查看:“”(必须向下查找)


      可以为启用自动完成。

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

      日志记录

      Python已经有了一个非常好的解决方案。您可能需要使用

      日志模块允许您指定重要性级别;在调试期间,您可以记录所有内容,而在正常操作期间,您可能只记录关键内容。你可以开关东西

      大多数人只是使用基本的print语句进行调试,然后删除print语句。最好把它们留在里面,但要禁用它们;然后,当您遇到另一个bug时,您可以重新启用所有功能并查看日志

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

      编辑:模板的原始URL为:

      此页面丢失,因此我将其替换为对存档网站上保存的快照的引用:

      如果它再次消失,下面是我提到的模板。这是来自博客的代码;不是我写的

      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
      

      PyDev

      有一个很好的交互式调试器。它有监视表达式、悬停求值、线程和堆栈列表,以及(几乎)现代可视化调试器提供的所有常用功能。您甚至可以连接到正在运行的进程并进行远程调试


      不过,和其他可视化调试器一样,我发现它在解决简单问题或非常复杂的问题时非常有用。我仍然使用日志完成大部分繁重的工作。

      在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>
      
      map-Oimport-rpdb2;rpdb2.start_嵌入式调试程序(“asdf”)#中断
      Rom nose.tools导入集的映射\u跟踪;设置_trace()#中断
      映射输入回溯,系统;traceback.print_异常(*sys.exc_info())#traceback
      
      rpdb2
      是一个远程Python调试器,可以与WinPDB一起使用,WinPDB是一个可靠的图形调试器。因为我知道您会问,它可以完成我期望的图形调试器所能完成的一切:)

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

      最后,
      F7
      映射将打印一个回溯(类似于异常冒泡到堆栈顶部时得到的回溯)。我不止几次发现它真的很有用。

      非常好,与它的名字相反,它完全是跨平台的


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

      如果使用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应用程序获取堆栈跟踪

      这里有几个技巧。其中包括

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

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

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

      ,这是一种基于控制台的全屏Python调试器

      它的目标是在一个更加轻量级和键盘友好的包中提供现代基于GUI的调试器的所有细节。PuDB允许您在编写和测试代码的地方调试代码——在终端中。如果您使用过优秀的(但现在已经过时的)基于DOS的TurboPascal或C工具,PuDB的UI可能看起来很熟悉
      python -m pudb.run my-script.py
      
      python -m pdb script.py
      
      python -m pdb ``which <python-script-name>``
      
      python -m trace -t setup.py install > execution.log
      
      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))