如何在Python中捕获包含源代码的错误回溯信息?
如何让exec执行代码时生成带源代码的错误回溯?
在VS Code笔记本或Python文件中直接运行代码时,错误回溯会包含出错的源代码行;但用exec执行相同代码块时,回溯仅显示行号和<string>,无法看到具体出错的源代码。以下是问题复现和解决方案:
直接运行代码的效果
运行以下代码:
def foo(): return 4/0 # 触发除以零异常 foo()
得到的详细回溯(包含源代码行):
--------------------------------------------------------------------------- ZeroDivisionError Traceback (most recent call last) Cell In[12], line 4 1 def foo(): 2 return 4/0 # 触发除以零异常 ----> 4 foo() Cell In[12], line 2, in foo() 1 def foo(): ----> 2 return 4/0 ZeroDivisionError: division by zero
使用exec运行的问题
运行以下代码:
import traceback import sys code = """def foo(): return 4/0 # 触发除以零异常 foo() """ try: exec(code) except Exception as e: traceback.print_exc()
得到的回溯(无源代码行):
Traceback (most recent call last): File "/var/folders/fd/f7mj1ws56pq6xvyzj4zv1r_m0000gn/T/ipykernel_39670/712868849.py", line 11, in <module> exec(code) File "<string>", line 4, in <module> File "<string>", line 2, in foo ZeroDivisionError: division by zero
解决方案
通过linecache模块将exec的代码添加到Python的源代码缓存,并给exec指定自定义文件名,让traceback能找到对应源代码。代码示例:
import traceback import sys import linecache code = """def foo(): return 4/0 # 触发除以零异常 foo() """ # 自定义文件名,用于标识这段exec代码 custom_filename = "exec_custom_code.py" # 将代码拆分后存入linecache缓存,供traceback查询 linecache.cache[custom_filename] = ( len(code), None, code.splitlines(keepends=True), custom_filename ) try: # 执行代码时指定全局命名空间中的__file__为自定义文件名 exec(code, {"__file__": custom_filename}) except Exception as e: # 格式化并打印包含源代码的回溯 traceback.print_exception(type(e), e, sys.exc_info()[2])
原理说明
exec的第二个参数是全局命名空间,指定__file__后,Python会将这段代码关联到自定义文件名,回溯中不再显示<string>。linecache是Python内置的源代码缓存模块,traceback在生成回溯时会通过该模块查找对应文件的源代码行,将exec代码存入缓存后,就能在回溯中显示具体出错的代码。
内容的提问来源于stack exchange,提问作者canonball
相关产品推荐
相关产品推荐

