traceback模块
终端报错输出
def f1(x, y):
return f2(x, y)
def f2(x, y):
return x / y
def f3():
res = f1(2, 0)
print(res)
if __name__ == '__main__':
f3()
python3 error_test.py
Traceback (most recent call last):
File "/Users/code/python_code/error_test.py", line 12, in <module>
f3()
File "/Users/code/python_code/error_test.py", line 8, in f3
res = f1(2, 0)
File "/Users/code/python_code/error_test.py", line 2, in f1
return f2(x, y)
File "/Users/code/python_code/error_test.py", line 5, in f2
return x / y
ZeroDivisionError: division by zero
使用异常捕获输出
import sys
import traceback
def f1(x, y):
return f2(x, y)
def f2(x, y):
return x / y
def f3():
res = f1(2, 0)
print(res)
if __name__ == '__main__':
try:
f3()
except Exception as e:
print(f"{type(e)}, {e}\n")
<class 'ZeroDivisionError'>, division by zero
使用sys.exc_info显示输出
案例
import sys
import traceback
def f1(x, y):
return f2(x, y)
def f2(x, y):
return x / y
def f3():
res = f1(2, 0)
print(res)
if __name__ == '__main__':
try:
f3()
except Exception:
exc_type, exc_value, exc_traceback_obj = sys.exc_info()
print("type ==> %s" % exc_type)
print("value ==> %s type: %s\n" %(exc_value, type(exc_value)))
print("traceback ==> exc_traceback_obj: %s" % exc_traceback_obj)
print("traceback ==> file name: %s" %(exc_traceback_obj.tb_frame.f_code.co_filename))
print("traceback ==> line no: %s" %(exc_traceback_obj.tb_lineno))
print("traceback ==> function name: %s" %(exc_traceback_obj.tb_frame.f_code.co_name))
type ==> <class 'ZeroDivisionError'>
value ==> division by zero type: <class 'ZeroDivisionError'>
traceback ==> exc_traceback_obj: <traceback object at 0x10296dd40>
traceback ==> file name: /Users/code/python_code/error_test.py
traceback ==> line no: 16
traceback ==> function name: <module>
使用traceback
print_xx方法
主要用于打印输出或者保存到文件中
traceback.print_tb
这个函数将堆栈跟踪信息打印到指定文件对象中,可以用于调试时输出详细的错误信息。
traceback.print_tb(tb, limit=None, file=None)
tb
: 表示堆栈跟踪的对象。limit
: 控制显示的堆栈帧数量。file
: 输出的文件对象,默认是sys.stderr
。
源码分析
def print_tb(tb, limit=None, file=None)
print_list(extract_tb(tb, limit=limit), file=file)
def print_list(extracted_list, file=None):
if file is None:
file = sys.stderr
for item in StackSummary.from_list(extracted_list).format():
print(item, file=file, end="")
什么是tb对象
tb是traceback对象
异常对象中获取
import traceback
import sys
def func1():
func2()
def func2():
func3()
def func3():
return 1 / 0
# 调用函数
try:
func1()
except Exception as e:
print(type(e.__traceback__))
print(e.__traceback__)
<class 'traceback'>
<traceback object at 0x100ac18c0>
sys.exc_info中获取
import traceback
import sys
def func1():
func2()
def func2():
func3()
def func3():
return 1 / 0
# 调用函数
try:
func1()
except Exception:
_,_, tb = sys.exc_info()
print(type(tb))
print(tb)
<class 'traceback'>
<traceback object at 0x1052598c0>
案例一:更具获取tb对象不同
获取异常对象的 __traceback__
import sys
import traceback
def f1(x, y):
return f2(x, y)
def f2(x, y):
return x / y
def f3():
res = f1(2, 0)
print(res)
try:
f3()
except ZeroDivisionError as e:
traceback.print_tb(tb=e.__traceback__)
File "/Users/code/python_code/error_test.py", line 14, in <module>
f3()
File "/Users/code/python_code/error_test.py", line 11, in f3
res = f1(2, 0)
File "/Users/code/python_code/error_test.py", line 5, in f1
return f2(x, y)
File "/Users/code/python_code/error_test.py", line 8, in f2
return x / y
获取sys.exc_info()
的traceback对象
推荐使用sys.exc_info()输出信息
import sys
import traceback
def f1(x, y):
return f2(x, y)
def f2(x, y):
return x / y
def f3():
res = f1(2, 0)
print(res)
try:
f3()
except ZeroDivisionError as e:
exc_type, exc_value, exc_traceback_obj = sys.exc_info()
traceback.print_tb(tb=exc_traceback_obj)
File "/Users/code/python_code/error_test.py", line 14, in <module>
f3()
File "/Users/code/python_code/error_test.py", line 11, in f3
res = f1(2, 0)
File "/Users/code/python_code/error_test.py", line 5, in f1
return f2(x, y)
File "/Users/code/python_code/error_test.py", line 8, in f2
return x / y
使用 sys.exc_info()
和使用异常对象的 __traceback__
属性区别
从使用的角度来看,通常推荐直接使用异常对象的
__traceback__
属性,因为它更直观,并且适用于当前异常的上下文。如果你需要获取当前线程的全局异常信息,那么可以使用sys.exc_info()
。
- 来源对象不同:
sys.exc_info()
返回一个包含异常信息的元组(exc_type, exc_value, exc_traceback)
,其中exc_traceback
是 traceback 对象。- 异常对象的
__traceback__
直接提供了 traceback 对象。
- 使用场景不同:
sys.exc_info()
可以在任何地方获取当前线程中的异常信息。它返回全局状态,适用于多线程环境。- 异常对象的
__traceback__
属性则直接从异常对象中获取,适用于当前异常对象的上下文。
案例二:使用limit
设置
limit=1
后,发现值查找深度为1层
import sys
import traceback
def f1(x, y):
return f2(x, y)
def f2(x, y):
return x / y
def f3():
res = f1(2, 0)
print(res)
try:
f3()
except ZeroDivisionError as e:
traceback.print_tb(tb=e.__traceback__, limit=1)
File "/Users/code/python_code/error_test.py", line 14, in <module>
f3()
案例三:使用file
import sys
import traceback
def f1(x, y):
return f2(x, y)
def f2(x, y):
return x / y
def f3():
res = f1(2, 0)
print(res)
try:
f3()
except ZeroDivisionError as e:
with open("traceback_output.txt", "w") as file:
traceback.print_tb(e.__traceback__, limit=None, file=file)
File "/Users/code/python_code/error_test.py", line 14, in <module>
f3()
File "/Users/code/python_code/error_test.py", line 11, in f3
res = f1(2, 0)
File "/Users/code/python_code/error_test.py", line 5, in f1
return f2(x, y)
File "/Users/code/python_code/error_test.py", line 8, in f2
return x / y
traceback.print_exception
这个函数将异常信息和堆栈跟踪信息打印到指定文件对象中,允许你输出完整的异常链信息。
traceback.print_exception(etype, value, tb, limit=None, file=None, chain=True)
etype
(type): 异常类型。value
(Exception对象): 异常实例。tb
(traceback对象): 堆栈跟踪对象。limit
(int, 可选): 控制打印的堆栈帧数量。file
(文件对象, 可选): 输出的文件对象,默认是sys.stderr
。chain
(bool, 可选): 如果为False
,则不会打印异常链的上一级异常。
源码
def print_exception(exc, /, value=_sentinel, tb=_sentinel, limit=None, \
file=None, chain=True):
value, tb = _parse_value_tb(exc, value, tb)
if file is None:
file = sys.stderr
te = TracebackException(type(value), value, tb, limit=limit, compact=True)
for line in te.format(chain=chain):
print(line, file=file, end="")
案例
import sys
import traceback
def f1(x, y):
return f2(x, y)
def f2(x, y):
return x / y
def f3():
res = f1(2, 0)
print(res)
try:
f3()
except ZeroDivisionError as e:
# 也可以使用一下案例,输出都是一样的
# traceback.print_exception(type(e), e, e.__traceback__)
traceback.print_exception(*sys.exc_info())
Traceback (most recent call last):
File "/Users/code/python_code/error_test.py", line 14, in <module>
f3()
File "/Users/code/python_code/error_test.py", line 11, in f3
res = f1(2, 0)
File "/Users/code/python_code/error_test.py", line 5, in f1
return f2(x, y)
File "/Users/code/python_code/error_test.py", line 8, in f2
return x / y
ZeroDivisionError: division by zero
traceback.print_exc
traceback.print_exc(limit=None, file=None, chain=True)
limit
(int, 可选): 控制打印的堆栈帧数量。file
(文件对象, 可选): 输出的文件对象,默认是sys.stderr
。chain
(bool, 可选): 如果为False
,则不会打印异常链的上一级异常。
源码
print_exception
这是print_exception(*sys.exc_info(), limit, file, chain)
的简写形式
def print_exc(limit=None, file=None, chain=True):
print_exception(*sys.exc_info(), limit=limit, file=file, chain=chain)
默认chain=True
import sys
import traceback
def f1(x, y):
try:
return f2(x, y)
except ZeroDivisionError as e:
raise ValueError("Custom error")
def f2(x, y):
return x / y
def f3():
res = f1(2, 0)
print(res)
try:
f3()
except ValueError as e:
traceback.print_exc(chain=True)
Traceback (most recent call last):
File "/Users/code/python_code/error_test.py", line 6, in f1
return f2(x, y)
File "/Users/code/python_code/error_test.py", line 11, in f2
return x / y
ZeroDivisionError: division by zero
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/Users/code/python_code/error_test.py", line 17, in <module>
f3()
File "/Users/code/python_code/error_test.py", line 14, in f3
res = f1(2, 0)
File "/Users/code/python_code/error_test.py", line 8, in f1
raise ValueError("Custom error")
ValueError: Custom error
设置chain=False
import sys
import traceback
def f1(x, y):
try:
return f2(x, y)
except ZeroDivisionError as e:
raise ValueError("Custom error")
def f2(x, y):
return x / y
def f3():
res = f1(2, 0)
print(res)
try:
f3()
except ValueError as e:
traceback.print_exc(chain=False)
Traceback (most recent call last):
File "/Users/code/python_code/error_test.py", line 17, in <module>
f3()
File "/Users/code/python_code/error_test.py", line 14, in f3
res = f1(2, 0)
File "/Users/code/python_code/error_test.py", line 8, in f1
raise ValueError("Custom error")
ValueError: Custom error
traceback.print_stack
函数用于打印当前堆栈的信息,显示调用函数的序列。这对于调试和了解程序执行路径非常有用。
traceback.print_stack(f=None, limit=None, file=None)
-
f
: 参数是一个可选的帧对象(frame对象并不是一个FrameSummary对象),用于指定提取信息的起点。 -
limit
(int, 可选): 控制打印的堆栈帧数量。 -
file
(文件对象, 可选): 输出的文件对象,默认是sys.stderr
。
源码
def print_stack(f=None, limit=None, file=None):
if f is None:
f = sys._getframe().f_back
print_list(extract_stack(f, limit=limit), file=file)
案例
import traceback
def example_function():
traceback.print_stack()
def another_function():
example_function()
another_function()
File "/Users/code/python_code/error_test.py", line 9, in <module>
another_function()
File "/Users/code/python_code/error_test.py", line 7, in another_function
example_function()
File "/Users/code/python_code/error_test.py", line 4, in example_function
traceback.print_stack()
format_xx方法
把print的输出内容转化为字符串列表形似返回
traceback.format_tb
这个函数返回一个
字符串
列表,其中包含有关堆栈跟踪的信息。通常用于将信息记录到文件或以其他形式存储和处理。
traceback.format_tb(tb, limit=None)
tb
:表示堆栈跟踪的对象。limit
: 控制显示的堆栈帧数量。如果为None
,则显示所有帧。
源码
def format_tb(tb, limit=None):
# extract_tb创建了StackSummary.extract(walk_tb(tb), limit=limit)对象,并使用format方法进行了处理
return extract_tb(tb, limit=limit).format()
limit为None
import sys
import traceback
def f1(x, y):
return f2(x, y)
def f2(x, y):
return x / y
def f3():
res = f1(2, 0)
print(res)
try:
f3()
except ZeroDivisionError as e:
exc_type, exc_value, exc_traceback_obj = sys.exc_info()
tb_list = traceback.format_tb(tb=exc_traceback_obj)
print(f"tb_list: {tb_list}")
print(">>>>>Traceback:")
print("".join(tb_list))
print(">>>>>Error:", e)
tb_list: [' File "/Users/code/python_code/error_test.py", line 14, in <module>\n f3()\n', ' File "/Users/code/python_code/error_test.py", line 11, in f3\n res = f1(2, 0)\n', ' File "/Users/code/python_code/error_test.py", line 5, in f1\n return f2(x, y)\n', ' File "/Users/code/python_code/error_test.py", line 8, in f2\n return x / y\n']
>>>>>Traceback:
File "/Users/code/python_code/error_test.py", line 14, in <module>
f3()
File "/Users/code/python_code/error_test.py", line 11, in f3
res = f1(2, 0)
File "/Users/code/python_code/error_test.py", line 5, in f1
return f2(x, y)
File "/Users/code/python_code/error_test.py", line 8, in f2
return x / y
>>>>>Error: division by zero
设置limit值
设置
limit=2
后,发现值查找深度为2层
import sys
import traceback
def f1(x, y):
return f2(x, y)
def f2(x, y):
return x / y
def f3():
res = f1(2, 0)
print(res)
try:
f3()
except ZeroDivisionError as e:
exc_type, exc_value, exc_traceback_obj = sys.exc_info()
tb_list = traceback.format_tb(tb=exc_traceback_obj, limit=2)
print(">>>>>Traceback:")
print("".join(tb_list))
print(">>>>>Error:", e)
>>>>>Traceback:
File "/Users/code/python_code/error_test.py", line 14, in <module>
f3()
File "/Users/code/python_code/error_test.py", line 11, in f3
res = f1(2, 0)
>>>>>Error: division by zero
traceback.format_exception
traceback.format_exception(etype, value, tb, limit=None, chain=True)
返回一个字符串列表,表示堆栈跟踪信息。
etype
: 异常类型。value
: 异常实例。tb
: 表示堆栈跟踪的对象。limit
: 控制显示的堆栈帧数量。chain
: 如果为False
,则不会显示异常链的上一级异常
源码
def format_exception(exc, /, value=_sentinel, tb=_sentinel, limit=None, \
chain=True):
value, tb = _parse_value_tb(exc, value, tb)
te = TracebackException(type(value), value, tb, limit=limit, compact=True)
return list(te.format(chain=chain))
案例
import sys
import traceback
def f1(x, y):
return f2(x, y)
def f2(x, y):
return x / y
def f3():
res = f1(2, 0)
print(res)
try:
f3()
except Exception:
res = traceback.format_exception(*sys.exc_info())
print(type(res))
print(res)
<class 'list'>
['Traceback (most recent call last):\n', ' File "/Users/code/python_code/error_test.py", line 14, in <module>\n f3()\n', ' File "/Users/code/python_code/error_test.py", line 11, in f3\n res = f1(2, 0)\n', ' File "/Users/code/python_code/error_test.py", line 5, in f1\n return f2(x, y)\n', ' File "/Users/code/python_code/error_test.py", line 8, in f2\n return x / y\n', 'ZeroDivisionError: division by zero\n']
traceback.format_exc
traceback.format_exc
是traceback.format_exception
的简写形式,返回一个字符串
"".join(format_exception(*sys.exc_info(), limit=limit, chain=chain))
format_exc(limit=None, chain=True)
limit
: 控制显示的堆栈帧数量。chain
: 如果为False
,则不会显示异常链的上一级异常。
import sys
import traceback
def f1(x, y):
return f2(x, y)
def f2(x, y):
return x / y
def f3():
res = f1(2, 0)
print(res)
try:
f3()
except Exception:
res = traceback.format_exc()
print(type(res))
print(res)
<class 'str'>
Traceback (most recent call last):
File "/Users/code/python_code/error_test.py", line 14, in <module>
f3()
File "/Users/code/python_code/error_test.py", line 11, in f3
res = f1(2, 0)
File "/Users/code/python_code/error_test.py", line 5, in f1
return f2(x, y)
File "/Users/code/python_code/error_test.py", line 8, in f2
return x / y
ZeroDivisionError: division by zero
traceback.format_stack
format_stack(f=None, limit=None)
f
: 参数是一个可选的帧对象(frame对象并不是一个FrameSummary对象),用于指定提取信息的起点。limit
: 控制显示的堆栈帧数量。
源码
def format_list(extracted_list):
return StackSummary.from_list(extracted_list).format()
def format_stack(f=None, limit=None):
# 调用了extract_stack,并使用format_list进行格式化
if f is None:
f = sys._getframe().f_back
return format_list(extract_stack(f, limit=limit))
案例
import traceback
def get_format_stack_info():
res = traceback.format_stack()
print(res)
get_format_stack_info()
[' File "/Users/code/python_code/error_test.py", line 7, in <module>\n get_format_stack_info()\n', ' File "/Users/code/python_code/error_test.py", line 4, in get_format_stack_info\n res = traceback.format_stack()\n']
extract_xx方法
比print_xx和format_xx更深入的方法
traceback.extract_tb
返回一个由
traceback.FrameSummary
对象组成的列表,每个对象表示一个堆栈帧
traceback.extract_tb(tb, limit=None)
tb
: 表示堆栈跟踪的对象。limit
: 控制显示的堆栈帧数量。
源码
def extract_tb(tb, limit=None):
return StackSummary.extract(walk_tb(tb), limit=limit)
def walk_tb(tb):
while tb is not None:
yield tb.tb_frame, tb.tb_lineno
tb = tb.tb_next
案例
import sys
import traceback
def f1(x, y):
return f2(x, y)
def f2(x, y):
return x / y
def f3():
res = f1(2, 0)
print(res)
try:
f3()
except ZeroDivisionError as e:
exc_type, exc_value, exc_traceback_obj = sys.exc_info()
# [traceback.FrameSummary, traceback.FrameSummary, ...]
traceback_framesummary_list = traceback.extract_tb(exc_traceback_obj)
for traceback_framesummary in traceback_framesummary_list:
"""
traceback_framesummary是traceback.FrameSummary对象
filename: 文件名
name: 方法名
lineno: 报错文件行号
line: 报错行对应的code
locals: 一个字典或者None
"""
print(f"-------{type(traceback_framesummary)}-------")
print(traceback_framesummary.filename, traceback_framesummary.name, traceback_framesummary.lineno)
print(traceback_framesummary.line)
print(traceback_framesummary.locals)
-------<class 'traceback.FrameSummary'>-------
/Users/code/python_code/error_test.py <module> 14
f3()
None
-------<class 'traceback.FrameSummary'>-------
/Users/code/python_code/error_test.py f3 11
res = f1(2, 0)
None
-------<class 'traceback.FrameSummary'>-------
/Users/code/python_code/error_test.py f1 5
return f2(x, y)
None
-------<class 'traceback.FrameSummary'>-------
/Users/code/python_code/error_test.py f2 8
return x / y
None
traceback.extract_stack
traceback.extract_stack(f=None, limit=None)
从当前调用栈中提取信息,返回一个由
FrameSummary
对象组成的列表。
f
参数是一个可选的帧对象(frame对象并不是一个FrameSummary对象),用于指定提取信息的起点。limit
参数用于控制显示的堆栈帧数量。
源码
def extract_stack(f=None, limit=None):
if f is None:
f = sys._getframe().f_back
stack = StackSummary.extract(walk_stack(f), limit=limit)
stack.reverse()
return stack
def walk_stack(f):
if f is None:
f = sys._getframe().f_back.f_back
while f is not None:
yield f, f.f_lineno
f = f.f_back
调用信息
import traceback
def get_extract_stack_info():
stack_info = traceback.extract_stack()
for frame in stack_info:
print(frame)
get_extract_stack_info()
<FrameSummary file /Users/code/python_code/error_test.py, line 8 in <module>>
<FrameSummary file /Users/code/python_code/error_test.py, line 4 in get_extract_stack_info>
多层调用栈信息
import sys
import traceback
def f1(x, y):
return f2(x, y)
def f2(x, y):
stack_info = traceback.extract_stack()
print("extract_stack information:")
for frame in stack_info:
print(frame)
return x + y
def f3():
res = f1(2, 0)
print(res)
f3()
extract_stack information:
<FrameSummary file /Users/code/python_code/error_test.py, line 18 in <module>>
<FrameSummary file /Users/code/python_code/error_test.py, line 15 in f3>
<FrameSummary file /Users/code/python_code/error_test.py, line 5 in f1>
<FrameSummary file /Users/code/python_code/error_test.py, line 8 in f2>
2
extract_stack和inspect.stack区别
traceback.extract_stack()
:
- 返回类型:返回一个列表,其中的每个元素是
FrameSummary
对象。- 提供的信息:主要包含了文件名、行号、函数名等基本信息,不提供局部变量等详细信息。
- 轻量级:由于提供的信息较为简略,
extract_stack()
在某些情况下可能会更轻量。- 用法:适用于只关注调用栈的基本结构,例如文件名、行号等。
inspect.stack()
:
- 返回类型:返回一个列表,其中的每个元素是
FrameInfo
对象。- 提供的信息:包含了更详细的信息,如局部变量、全局变量等。
FrameInfo
对象比FrameSummary
提供更多的上下文信息。- 更全面:提供更全面的堆栈信息,适用于需要深入了解调用栈上下文的情况。
- 用法:适用于需要更详细的调用栈信息,比如查看局部变量的值等。
import traceback
import inspect
def get_extract_stack_info():
stack_info = traceback.extract_stack()
print("extract_stack information:")
for frame in stack_info:
print(frame)
def get_inspect_info():
print("\nInspect information:")
inspect_info = inspect.stack()
for frame, _, _, _, _, _ in inspect_info:
print(frame)
get_extract_stack_info()
get_inspect_info()
extract_stack information:
<FrameSummary file /Users/code/python_code/error_test.py, line 16 in <module>>
<FrameSummary file /Users/code/python_code/error_test.py, line 5 in get_extract_stack_info>
Inspect information:
<frame at 0x1032c19a0, file '/Users/code/python_code/error_test.py', line 14, code get_inspect_info>
<frame at 0x1030d1a40, file '/Users/code/python_code/error_test.py', line 18, code <module>>
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义