2011-06-05 91 views
21

有时在我调试时会引发异常。如何在Python调试器中看到异常的细节?

例如,考虑下面的代码:

def some_function(): # Pretend this function is in a library... 
    # ...and deep within the library is an exception: 
    raise Exception('An exception message with valuable information.') 

import pdb; pdb.set_trace() 
try: 
    some_function() # Pretend I am debugging from this point using pdb. 
except: 
    pass 

虽然从some_function()通话调试,如果我发出了一个next命令我会看到有关有人提出[一把抓住]除了以下细节:

Exception: Exceptio...ation.',) 

这里是从终端直复制/粘贴我在工作:

> /tmp/test.py(7)<module>() 
-> some_function() # Pretend I am debugging from this point using pdb. 
(Pdb) next 
Exception: Exceptio...ation.',) 
> /tmp/test.py(7)<module>() 
-> some_function() # Pretend I am debugging from this point using pdb. 
(Pdb) 

查看整个异常消息将非常有用。我怎样才能在pdb中做到这一点?

+0

您使用的是什么版本的Python?我的矿井不会像那样截断。 – Keith 2011-06-05 08:46:53

+0

版本2.7.1。请注意,raise语句是完整打印的,所以乍一看你可能会打印整个异常,但是当实际的异常被pdb截取(我不知道这个术语)时,它会被截断。 – Buttons840 2011-06-05 17:43:05

+0

嗯,我实际上编写了我自己的Python调试器的变体,它不会这样做,也意味着自动进入调试器(使用sys.excepthook)。如果你喜欢,你可以尝试一下。它是[调试器](http://code.google.com/p/pycopia/source/browse/#svn%2Ftrunk%2Fdebugger)子包。 – Keith 2011-06-06 01:44:55

回答

19

pdb存储异常类型和价值倾倒在你的代码中的任何点的堆栈跟踪。

import traceback; print "".join(traceback.format_exception_only(*__exception__)) 

例如:你可以用打印回溯外部分pdb

> /tmp/test.py(7)<module>() 
-> some_function() # Pretend I am debugging from this point using pdb. 
(Pdb) next 
Exception: Exceptio...ation.',) 
> /tmp/test.py(7)<module>() 
-> some_function() # Pretend I am debugging from this point using pdb. 
(Pdb) import traceback; print "".join(traceback.format_exception_only(*__exception__)) 
Exception: An exception message with valuable information. 

(Pdb) 

不幸的是,这并不包括回溯的休息,但所有这些信息是可以通过where无论如何,pdb的命令。如果你真的想完整回溯,你可以添加以下到您的~/.pdbrc文件或粘贴到你的终端:

!global __currentframe, __stack; from inspect import currentframe as __currentframe, stack as __stack 
!global __format_exception_only, __print_stack; from traceback import format_exception_only as __format_exception_only, print_stack as __print_stack 
!global __Pdb; from pdb import Pdb as __Pdb 

# find the last frame on the stack with an object named "pdb" or "self" that is a pdb.Pdb object 
# works for pdb called the usual way, or pdb.pm(), or pdb.set_trace() 
!global __pdb; __pdb = [__framerec[0].f_locals.get("pdb") or __framerec[0].f_locals.get("self") for __framerec in __stack() if (__framerec[0].f_locals.get("pdb") or __framerec[0].f_locals.get("self")).__class__ == __Pdb][-1] 

alias traceback __print_stack(__pdb.stack[-1][0]); print "".join(__format_exception_only(*__exception__)) 

然后,你可以使用新的traceback别名得到你想要的东西:

> /tmp/test.py(7)<module>() 
-> some_function() # Pretend I am debugging from this point using pdb. 
(Pdb) next 
Exception: Exceptio...ation.',) 
> /tmp/test.py(7)<module>() 
-> some_function() # Pretend I am debugging from this point using pdb. 
(Pdb) traceback 
    File "test.py", line 7, in <module> 
    some_function() # Pretend I am debugging from this point using pdb. 
    File "test.py", line 3, in some_function 
    raise Exception('An exception message with valuable information.') 
Exception: An exception message with valuable information. 

(Pdb) 

警告:所有这些都依赖于未公开的pdbbdb内部组件,并且可能会中断。

+0

非常有用的黑客感谢您。令人失望的是,没有正常的方法去做一些如此常见和有用的事情。这个黑客也适用于pdb ++,所以我通过'ipdb'切换到那个。 – DBedrenko 2015-11-04 11:42:50

6

python调试器不会“打破异常” - 如果您习惯了这种功能,这可能会非常令人沮丧。因此,我采取了记录痕迹并从那里回来的政策。

import logging 
try: 
    raise Exception('An exception message with valuable information.') 
except: 
    logging.exception('Error in test code') 

如果你使用一个很好的IDE(如Eclipse与PyDev的),对于堆栈跟踪日志条目由成直接跳到在代码中适当的位置上的超链接。

您可以通过在__exception__进口回溯

import traceback 
trace = traceback.format_exc() 
+2

最好使用'日志记录。记录异常追踪的异常('Informative message')'以及关于失败操作的任何信息('信息性消息',可以有参数等)。您可以使用'logging.debug(...,exc_info = True)'在任何级别(例如DEBUG)登录。 – 2011-06-05 08:36:41

+0

我没有意识到这一点 - 感谢Vinay。如果您没有问题,我会更新我的答案? – 2011-06-05 08:48:41

+0

我正在使用twisted.python.log。我可以使用日志记录,但我宁愿不。此外,尝试:提高;除了:...不在我的代码中,但在某处扭曲,(至少我是这么认为的)。所以如果我要使用这样的日志记录,我将不得不修改扭曲的代码。 – Buttons840 2011-06-05 17:45:22