traceback
— 打印或检索堆栈回溯¶
源代码: Lib/traceback.py
此模块提供了一个标准接口,用于提取、格式化和打印 Python 程序的堆栈跟踪。 它比解释器的默认回溯显示更灵活,因此可以配置输出的某些方面。 最后,它包含一个实用程序,用于捕获有关异常的足够信息,以便稍后打印它,而无需保存对实际异常的引用。 由于异常可能是大型对象图的根,因此此实用程序可以显着改善内存管理。
该模块使用 回溯对象 — 这些是 types.TracebackType
类型的对象,它们被分配给 __traceback__
BaseException
实例的字段。
另请参阅
- 模块
faulthandler
用于在故障、超时后或在用户信号上显式转储 Python 回溯。
- 模块
pdb
用于 Python 程序的交互式源代码调试器。
该模块的 API 可以分为两部分
模块级函数提供基本功能,这对于交互式检查异常和回溯非常有用。
TracebackException
类及其辅助类StackSummary
和FrameSummary
。 这些在生成的输出中提供了更大的灵活性,并且能够存储稍后格式化所需的信息,而无需保留对实际异常和回溯对象的引用。
模块级函数¶
- traceback.print_tb(tb, limit=None, file=None)¶
如果 limit 为正,则从 回溯对象 tb (从调用者的帧开始)打印最多 limit 个堆栈跟踪条目。 否则,打印最后
abs(limit)
个条目。 如果省略 limit 或为None
,则打印所有条目。 如果省略 file 或为None
,则输出转到sys.stderr
;否则它应该是一个打开的 文件 或 类文件对象 来接收输出。注意
limit 参数的含义与
sys.tracebacklimit
的含义不同。 负 limit 值对应于sys.tracebacklimit
的正值,而正 limit 值的行为无法通过sys.tracebacklimit
实现。在 3.5 版本中更改: 添加了负 limit 支持。
- traceback.print_exception(exc, /, [value, tb, ]limit=None, file=None, chain=True)¶
将来自 回溯对象 tb 的异常信息和堆栈跟踪条目打印到 file。 这与
print_tb()
不同,具体如下如果 tb 不是
None
,它会打印一个标头Traceback (most recent call last):
它在堆栈跟踪之后打印异常类型和 value
如果 type(value) 是
SyntaxError
并且 value 具有适当的格式,它会打印发生语法错误的行,并带有一个插入符号,指示错误的大概位置。
从 Python 3.10 开始,可以传递异常对象作为第一个参数,而不是传递 value 和 tb。 如果提供了 value 和 tb,则会忽略第一个参数,以提供向后兼容性。
可选的 limit 参数与
print_tb()
的含义相同。 如果 chain 为 true(默认),则还将打印链接的异常(异常的__cause__
或__context__
属性),就像解释器在打印未处理的异常时所做的那样。在 3.5 版本中更改: 忽略 etype 参数,并从 value 的类型推断出来。
在 3.10 版本中更改: etype 参数已重命名为 exc,现在是仅限位置的。
- traceback.print_exc(limit=None, file=None, chain=True)¶
这是
print_exception(sys.exception(), limit, file, chain)
的简写。
- traceback.print_last(limit=None, file=None, chain=True)¶
这是
print_exception(sys.last_exc, limit, file, chain)
的简写形式。一般来说,它只有在异常到达交互式提示符后才起作用(请参阅sys.last_exc
)。
- traceback.print_stack(f=None, limit=None, file=None)¶
如果 limit 为正数,则打印最多 limit 个堆栈跟踪条目(从调用点开始)。否则,打印最后
abs(limit)
个条目。如果省略 limit 或为None
,则打印所有条目。可选参数 f 可用于指定要开始的备用 堆栈帧。可选参数 file 的含义与print_tb()
中的含义相同。在 3.5 版本中更改: 添加了负 limit 支持。
- traceback.extract_tb(tb, limit=None)¶
返回一个
StackSummary
对象,该对象表示从 回溯对象 tb 中提取的“预处理”堆栈跟踪条目列表。它对于堆栈跟踪的替代格式很有用。可选参数 limit 的含义与print_tb()
中的含义相同。“预处理”堆栈跟踪条目是一个FrameSummary
对象,其中包含属性filename
、lineno
、name
和line
,这些属性表示通常为堆栈跟踪打印的信息。
- traceback.extract_stack(f=None, limit=None)¶
从当前的 堆栈帧 中提取原始回溯。返回值与
extract_tb()
的格式相同。可选参数 f 和 limit 的含义与print_stack()
中的含义相同。
- traceback.print_list(extracted_list, file=None)¶
将由
extract_tb()
或extract_stack()
返回的元组列表作为格式化的堆栈跟踪打印到给定的文件。如果 file 为None
,则将输出写入sys.stderr
。
- traceback.format_list(extracted_list)¶
给定一个元组列表或由
extract_tb()
或extract_stack()
返回的FrameSummary
对象,返回一个准备打印的字符串列表。结果列表中的每个字符串都对应于参数列表中具有相同索引的项。每个字符串都以换行符结尾;对于那些源文本行不是None
的项,字符串也可能包含内部换行符。
- traceback.format_exception_only(exc, /, [value, ]*, show_group=False)¶
使用异常值(例如由
sys.last_value
给出的值)格式化回溯的异常部分。返回值是一个字符串列表,每个字符串都以换行符结尾。该列表包含异常的消息,通常是一个字符串;但是,对于SyntaxError
异常,它包含多行,这些行(在打印时)显示有关语法错误发生位置的详细信息。在消息之后,该列表包含异常的notes
。自 Python 3.10 起,可以传递异常对象作为第一个参数,而不是传递 value。如果提供了 value,则为了提供向后兼容性,将忽略第一个参数。
当 show_group 为
True
且异常是BaseExceptionGroup
的实例时,嵌套异常也将被递归包含,并带有相对于其嵌套深度的缩进。在 3.10 版本中更改: etype 参数已重命名为 exc,现在是仅限位置的。
在 3.11 版本中更改: 现在,返回的列表包含附加到异常的任何
notes
。在 3.13 版本中更改: 添加了 show_group 参数。
- traceback.format_exception(exc, /, [value, tb, ]limit=None, chain=True)¶
格式化堆栈跟踪和异常信息。参数的含义与
print_exception()
的对应参数的含义相同。返回值是一个字符串列表,每个字符串都以换行符结尾,其中一些包含内部换行符。当这些行被连接和打印时,打印的文本与print_exception()
完全相同。在 3.5 版本中更改: 忽略 etype 参数,并从 value 的类型推断出来。
在 3.10 版本中更改: 此函数的行为和签名已修改为与
print_exception()
匹配。
- traceback.format_exc(limit=None, chain=True)¶
此函数类似于
print_exc(limit)
,但返回的是字符串而不是打印到文件。
- traceback.format_tb(tb, limit=None)¶
是
format_list(extract_tb(tb, limit))
的简写形式。
- traceback.format_stack(f=None, limit=None)¶
是
format_list(extract_stack(f, limit))
的简写形式。
- traceback.walk_stack(f)¶
从给定帧开始,按照
f.f_back
遍历堆栈,并为每个帧生成帧和行号。如果 *f* 为None
,则使用当前堆栈。此辅助函数与StackSummary.extract()
一起使用。3.5 版本新增。
- traceback.walk_tb(tb)¶
按照
tb_next
遍历回溯,并为每个帧生成帧和行号。此辅助函数与StackSummary.extract()
一起使用。3.5 版本新增。
TracebackException
对象¶
3.5 版本新增。
TracebackException
对象由实际的异常创建,用于捕获数据以供后续打印。它们提供了一种更轻量级的方法来存储此信息,避免持有对 回溯 和 帧 对象的引用。此外,与上述模块级函数相比,它们公开了更多配置输出的选项。
- class traceback.TracebackException(exc_type, exc_value, exc_traceback, *, limit=None, lookup_lines=True, capture_locals=False, compact=False, max_group_width=15, max_group_depth=10)¶
捕获异常以便稍后呈现。 *limit*、*lookup_lines* 和 *capture_locals* 的含义与
StackSummary
类相同。如果 *compact* 为 true,则只在类属性中保存
TracebackException
的format()
方法所需的数据。 特别是,只有当__cause__
为None
且__suppress_context__
为 false 时,才会计算__context__
字段。请注意,当捕获局部变量时,它们也会显示在回溯中。
*max_group_width* 和 *max_group_depth* 控制异常组的格式(请参阅
BaseExceptionGroup
)。深度是指组的嵌套级别,而宽度是指单个异常组的异常数组的大小。当超出任一限制时,格式化输出会被截断。在 3.10 版本中变更: 添加了 *compact* 参数。
在 3.11 版本中变更: 添加了 *max_group_width* 和 *max_group_depth* 参数。
- __context__¶
原始
__context__
的TracebackException
。
- exceptions¶
如果
self
表示一个ExceptionGroup
,则此字段包含一个TracebackException
实例列表,表示嵌套的异常。否则为None
。3.11 版本新增。
- __suppress_context__¶
原始异常中的
__suppress_context__
值。
- stack¶
表示回溯的
StackSummary
。
- exc_type¶
原始回溯的类。
3.13 版本起已弃用。
- exc_type_str¶
原始异常的类的字符串显示。
3.13 版本新增。
- filename¶
对于语法错误 - 发生错误的文件名。
- lineno¶
对于语法错误 - 发生错误的行号。
- end_lineno¶
对于语法错误 - 发生错误的结束行号。如果不存在,则可以为
None
。在版本 3.10 中添加。
- text¶
对于语法错误 - 发生错误的文本。
- offset¶
对于语法错误 - 错误在文本中发生的偏移量。
- end_offset¶
对于语法错误 - 错误在文本中发生的结束偏移量。如果不存在,则可以为
None
。在版本 3.10 中添加。
- msg¶
对于语法错误 - 编译器错误消息。
- classmethod from_exception(exc, *, limit=None, lookup_lines=True, capture_locals=False)¶
捕获异常以供稍后渲染。limit、lookup_lines 和 capture_locals 与
StackSummary
类相同。请注意,当捕获局部变量时,它们也会显示在回溯中。
- format(*, chain=True)¶
格式化异常。
如果 chain 不是
True
,则不会格式化__cause__
和__context__
。返回值是一个字符串生成器,每个字符串都以换行符结尾,并且有些字符串包含内部换行符。
print_exception()
是对此方法的包装,它只是将行打印到文件中。
- format_exception_only(*, show_group=False)¶
格式化回溯的异常部分。
返回值是一个字符串生成器,每个字符串都以换行符结尾。
当 show_group 为
False
时,生成器会发出异常的消息,后跟其注释(如果有)。异常消息通常是单个字符串;但是,对于SyntaxError
异常,它由多行组成,这些行(打印时)显示有关语法错误发生位置的详细信息。当 show_group 为
True
且异常是BaseExceptionGroup
的实例时,嵌套异常也将被递归包含,并带有相对于其嵌套深度的缩进。在 3.11 版本中更改: 异常的
notes
现在包含在输出中。在 3.13 版本中更改: 添加了 show_group 参数。
StackSummary
对象¶
3.5 版本新增。
StackSummary
对象表示准备好格式化的调用堆栈。
- class traceback.StackSummary¶
- classmethod extract(frame_gen, *, limit=None, lookup_lines=True, capture_locals=False)¶
从帧生成器(例如由
walk_stack()
或walk_tb()
返回的生成器)构造StackSummary
对象。如果提供了 limit,则仅从 frame_gen 中获取这么多帧。如果 lookup_lines 为
False
,则返回的FrameSummary
对象将不会读取它们的行,从而降低创建StackSummary
的成本(如果它可能实际上不会被格式化,这可能会很有价值)。如果 capture_locals 为True
,则每个FrameSummary
中的局部变量将作为对象表示形式捕获。在 3.12 版本中更改: 当 capture_locals 为
True
时,从局部变量上的repr()
引发的异常不再传播给调用者。
- classmethod from_list(a_list)¶
从提供的
FrameSummary
对象列表或旧式元组列表构造StackSummary
对象。每个元组都应该是包含 filename、lineno、name、line 作为元素的 4 元组。
- format()¶
返回准备打印的字符串列表。结果列表中的每个字符串都对应于堆栈中的单个 frame。每个字符串都以换行符结尾;这些字符串也可能包含内部换行符,对于那些带有源代码文本行的项目。
对于相同帧和行的长序列,会显示前几个重复项,后跟一个摘要行,说明进一步重复的确切次数。
在 3.6 版本中更改: 现在会缩写重复帧的长序列。
- format_frame_summary(frame_summary)¶
返回一个用于打印堆栈中涉及的 frames 之一的字符串。对于要由
StackSummary.format()
打印的每个FrameSummary
对象,都会调用此方法。如果它返回None
,则该帧将从输出中省略。3.11 版本新增。
FrameSummary
对象¶
3.5 版本新增。
FrameSummary
对象表示 traceback 中的单个 frame。
- class traceback.FrameSummary(filename, lineno, name, lookup_line=True, locals=None, line=None)¶
表示在格式化或打印的回溯或堆栈中的单个帧。它可以选择性地包含帧的局部变量的字符串化版本。如果 lookup_line 为
False
,则在FrameSummary
访问line
属性(当将其转换为tuple
时也会发生)之前,不会查找源代码。可以直接提供line
,这将阻止所有行查找发生。locals 是一个可选的局部变量映射,如果提供,变量表示形式将存储在摘要中以供稍后显示。FrameSummary
实例具有以下属性- filename¶
此帧的源代码文件名。等效于访问
f.f_code.co_filename
在帧对象 f 上。
- lineno¶
此帧的源代码行号。
- name¶
等效于访问
f.f_code.co_name
在帧对象 f 上。
- line¶
表示此帧的源代码的字符串,其中删除了开头和结尾的空格。如果源代码不可用,则为
None
。
使用模块级函数的示例¶
这个简单的示例实现了一个基本的读取-求值-打印循环,类似于(但不如)标准的 Python 交互式解释器循环。有关解释器循环的更完整实现,请参阅 code
模块。
import sys, traceback
def run_user_code(envdir):
source = input(">>> ")
try:
exec(source, envdir)
except Exception:
print("Exception in user code:")
print("-"*60)
traceback.print_exc(file=sys.stdout)
print("-"*60)
envdir = {}
while True:
run_user_code(envdir)
以下示例演示了打印和格式化异常和回溯的不同方法
import sys, traceback
def lumberjack():
bright_side_of_life()
def bright_side_of_life():
return tuple()[0]
try:
lumberjack()
except IndexError as exc:
print("*** print_tb:")
traceback.print_tb(exc.__traceback__, limit=1, file=sys.stdout)
print("*** print_exception:")
traceback.print_exception(exc, limit=2, file=sys.stdout)
print("*** print_exc:")
traceback.print_exc(limit=2, file=sys.stdout)
print("*** format_exc, first and last line:")
formatted_lines = traceback.format_exc().splitlines()
print(formatted_lines[0])
print(formatted_lines[-1])
print("*** format_exception:")
print(repr(traceback.format_exception(exc)))
print("*** extract_tb:")
print(repr(traceback.extract_tb(exc.__traceback__)))
print("*** format_tb:")
print(repr(traceback.format_tb(exc.__traceback__)))
print("*** tb_lineno:", exc.__traceback__.tb_lineno)
示例的输出将类似于这样
*** print_tb:
File "<doctest...>", line 10, in <module>
lumberjack()
~~~~~~~~~~^^
*** print_exception:
Traceback (most recent call last):
File "<doctest...>", line 10, in <module>
lumberjack()
~~~~~~~~~~^^
File "<doctest...>", line 4, in lumberjack
bright_side_of_life()
~~~~~~~~~~~~~~~~~~~^^
IndexError: tuple index out of range
*** print_exc:
Traceback (most recent call last):
File "<doctest...>", line 10, in <module>
lumberjack()
~~~~~~~~~~^^
File "<doctest...>", line 4, in lumberjack
bright_side_of_life()
~~~~~~~~~~~~~~~~~~~^^
IndexError: tuple index out of range
*** format_exc, first and last line:
Traceback (most recent call last):
IndexError: tuple index out of range
*** format_exception:
['Traceback (most recent call last):\n',
' File "<doctest default[0]>", line 10, in <module>\n lumberjack()\n ~~~~~~~~~~^^\n',
' File "<doctest default[0]>", line 4, in lumberjack\n bright_side_of_life()\n ~~~~~~~~~~~~~~~~~~~^^\n',
' File "<doctest default[0]>", line 7, in bright_side_of_life\n return tuple()[0]\n ~~~~~~~^^^\n',
'IndexError: tuple index out of range\n']
*** extract_tb:
[<FrameSummary file <doctest...>, line 10 in <module>>,
<FrameSummary file <doctest...>, line 4 in lumberjack>,
<FrameSummary file <doctest...>, line 7 in bright_side_of_life>]
*** format_tb:
[' File "<doctest default[0]>", line 10, in <module>\n lumberjack()\n ~~~~~~~~~~^^\n',
' File "<doctest default[0]>", line 4, in lumberjack\n bright_side_of_life()\n ~~~~~~~~~~~~~~~~~~~^^\n',
' File "<doctest default[0]>", line 7, in bright_side_of_life\n return tuple()[0]\n ~~~~~~~^^^\n']
*** tb_lineno: 10
以下示例显示了打印和格式化堆栈的不同方法
>>> import traceback
>>> def another_function():
... lumberstack()
...
>>> def lumberstack():
... traceback.print_stack()
... print(repr(traceback.extract_stack()))
... print(repr(traceback.format_stack()))
...
>>> another_function()
File "<doctest>", line 10, in <module>
another_function()
File "<doctest>", line 3, in another_function
lumberstack()
File "<doctest>", line 6, in lumberstack
traceback.print_stack()
[('<doctest>', 10, '<module>', 'another_function()'),
('<doctest>', 3, 'another_function', 'lumberstack()'),
('<doctest>', 7, 'lumberstack', 'print(repr(traceback.extract_stack()))')]
[' File "<doctest>", line 10, in <module>\n another_function()\n',
' File "<doctest>", line 3, in another_function\n lumberstack()\n',
' File "<doctest>", line 8, in lumberstack\n print(repr(traceback.format_stack()))\n']
最后一个示例演示了最后几个格式化函数
>>> import traceback
>>> traceback.format_list([('spam.py', 3, '<module>', 'spam.eggs()'),
... ('eggs.py', 42, 'eggs', 'return "bacon"')])
[' File "spam.py", line 3, in <module>\n spam.eggs()\n',
' File "eggs.py", line 42, in eggs\n return "bacon"\n']
>>> an_error = IndexError('tuple index out of range')
>>> traceback.format_exception_only(an_error)
['IndexError: tuple index out of range\n']
使用 TracebackException
的示例¶
有了辅助类,我们有更多的选择
>>> import sys
>>> from traceback import TracebackException
>>>
>>> def lumberjack():
... bright_side_of_life()
...
>>> def bright_side_of_life():
... t = "bright", "side", "of", "life"
... return t[5]
...
>>> try:
... lumberjack()
... except IndexError as e:
... exc = e
...
>>> try:
... try:
... lumberjack()
... except:
... 1/0
... except Exception as e:
... chained_exc = e
...
>>> # limit works as with the module-level functions
>>> TracebackException.from_exception(exc, limit=-2).print()
Traceback (most recent call last):
File "<python-input-1>", line 6, in lumberjack
bright_side_of_life()
~~~~~~~~~~~~~~~~~~~^^
File "<python-input-1>", line 10, in bright_side_of_life
return t[5]
~^^^
IndexError: tuple index out of range
>>> # capture_locals adds local variables in frames
>>> TracebackException.from_exception(exc, limit=-2, capture_locals=True).print()
Traceback (most recent call last):
File "<python-input-1>", line 6, in lumberjack
bright_side_of_life()
~~~~~~~~~~~~~~~~~~~^^
File "<python-input-1>", line 10, in bright_side_of_life
return t[5]
~^^^
t = ("bright", "side", "of", "life")
IndexError: tuple index out of range
>>> # The *chain* kwarg to print() controls whether chained
>>> # exceptions are displayed
>>> TracebackException.from_exception(chained_exc).print()
Traceback (most recent call last):
File "<python-input-19>", line 4, in <module>
lumberjack()
~~~~~~~~~~^^
File "<python-input-8>", line 7, in lumberjack
bright_side_of_life()
~~~~~~~~~~~~~~~~~~~^^
File "<python-input-8>", line 11, in bright_side_of_life
return t[5]
~^^^
IndexError: tuple index out of range
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "<python-input-19>", line 6, in <module>
1/0
~^~
ZeroDivisionError: division by zero
>>> TracebackException.from_exception(chained_exc).print(chain=False)
Traceback (most recent call last):
File "<python-input-19>", line 6, in <module>
1/0
~^~
ZeroDivisionError: division by zero