Python从哪里检索<filename> traceback条目字段?

问题描述 投票:3回答:2

每个回溯项都有一个类似的格式。

File "<filename>", line xxx, in <module>
    line

我有兴趣改变某些模块的文件名字段(改成自定义的)。这可能吗?我试过修改 __file__ 成员,但当python生成回溯栈时,似乎并没有用到。

python intercept traceback
2个回答
1
投票

你可以使用 inspect 模块来获取多个模块的文件路径,例如:。

>>> inspect.getabsfile(traceback)
'/usr/local/Cellar/python3/3.4.2_1/Frameworks/Python.framework/Versions/3.4/lib/python3.4/traceback.py'

知道回溯来自于 traceback.print_stack()的定义,然后我们可以看一下 print_stack():

279 def print_stack(f=None, limit=None, file=None):
280     """Print a stack trace from its invocation point.
281
282     The optional 'f' argument can be used to specify an alternate
283     stack frame at which to start. The optional 'limit' and 'file'
284     arguments have the same meaning as for print_exception().
285     """
286     print_list(extract_stack(_get_stack(f), limit=limit), file=file)

说完了 "在哪里定义的?",我就省去你跟着函数调用的麻烦了,建议你看一下 format_exception相关例子. 在不知道你想用回溯做什么的情况下,我建议你看一看 jinja2源 因为它做了不少的回溯篡改。


0
投票

打印这一行的代码是在CPython的代码里面,在函数 tb_displayline() 的traceback.c:

https:/github.comythoncpythonblob3.9Pythontraceback.c#L511

调用堆栈很简单。

PyTraceBack_Print()tb_printinternal()tb_displayline()

从这些函数的代码来看,如果不在CPython的源头上做手脚,是无法在解释器内突变代码框架对象的。另外,在CPython中的 co_filename 的属性被定义为只读。https:/github.compythoncpythonblob3.9Objectscodeobject.c#L388。

信息: PyTraceBack_Print() 从两个地方叫。

  • print_exception() 在Pythonpythonrun.c中
  • write_unraisable_exc_file() 中的Pythonerrors.c

所以不可能修改从文件导入的模块的文件名,因为在这种情况下,加载器是由 SourceFileLoader 它不允许修改文件名。SourceFileLoader 可在这里获得。https:/github.comythoncpythonblob3.9Libimportlib_bootstrap_external.py#L1013。

内建模块是一种特殊的情况:因为它们是在CPython解释器中用C语言实现的,所以它们有了 "built-in" 陷于 co_filename 领域。这里就完成了。https:/github.comythoncpythonblob3.9Libimportlib_bootstrap.py#L725。

但遗憾的是没有办法为已经导入的模块设置一个任意的名字。

甚至不希望替换源文件路径,因为没有从traceback中得到源文件路径,会增加调试的难度。

© www.soinside.com 2019 - 2024. All rights reserved.