如何在Python调试器中查看异常详情?

30 投票
3 回答
15133 浏览
提问于 2025-04-16 18:58

有时候在调试的时候,会出现异常情况。

比如,看看这段代码:

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 中做到这一点呢?

3 个回答

0

你可以使用:

import sys
sys.exc_info()

在VSCode中,可以在底部的调试栏输入导入的内容。

7

Python的调试器并不会像其他一些工具那样在出现错误时自动中断,这可能会让习惯了这种功能的人感到有些沮丧。因此,我通常会选择记录错误信息,然后从这些信息中找出问题所在。

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

如果你使用一个好的开发环境,比如带有pydev的Eclipse,错误信息中的堆栈跟踪会变成可以点击的链接,直接跳转到代码中的相关位置。

你可以通过导入traceback模块,在代码的任何地方输出堆栈跟踪信息。

import traceback
trace = traceback.format_exc()
29

pdb 会把异常的类型和内容存储在 __exception__ 里。你可以用下面的命令在 pdb 中打印出异常的部分:

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

举个例子:

> /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) 

不过遗憾的是,这个命令不会显示完整的错误追踪信息,但你可以通过 pdbwhere 命令获取到所有相关的信息。如果你真的想要完整的错误追踪信息,可以把下面的内容添加到你的 ~/.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 的内部实现,可能会出现问题。

撰写回答