Python从哪里检索</filename>中的<filename> traceback entry字段

时间:2014-12-15 15:11:46

标签: python intercept traceback

每个追溯项目的格式如下:

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

我有兴趣更改某些模块的文件名字段(自定义)。这可能吗?我已经尝试修改模块对象的__file__成员,但是当python生成回溯堆栈时似乎没有使用它。

2 个答案:

答案 0 :(得分:2)

您可以使用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_exceptionrelevant examples。如果不明确知道你想用回溯做什么,我建议你查看jinja2 source,因为它会进行相当多的追溯修复。

答案 1 :(得分:0)

打印此行的代码在CPython的代码内部,位于traceback.c的函数tb_displayline()中:

https://github.com/python/cpython/blob/3.9/Python/traceback.c#L511

调用堆栈很容易理解:

PyTraceBack_Print()tb_printinternal()tb_displayline()

查看这些函数的代码,如果不修改CPython的源代码,就不可能从解释器中更改代码框架对象。同样,代码帧的co_filename属性被定义为只读:https://github.com/python/cpython/blob/3.9/Objects/codeobject.c#L388

有关信息,从两个地方调用PyTraceBack_Print()

  • 来自Python / pythonrun.c中的print_exception()
  • 来自write_unraisable_exc_file(),来自Python / errors.c

因此,无法修改从文件导入的模块的文件名,因为在这种情况下,加载程序为SourceFileLoader,不允许修改文件名。 SourceFileLoader的源代码可在以下位置找到:https://github.com/python/cpython/blob/3.9/Lib/importlib/_bootstrap_external.py#L1013

Builtin模块是特殊情况:由于它们是在CPython解释器中用C实现的,因此在"built-in"字段中设置了co_filename。在这里完成:https://github.com/python/cpython/blob/3.9/Lib/importlib/_bootstrap.py#L725

但是不幸的是,无法为已导入的模块设置任意名称。

甚至不希望替换源文件路径,因为如果没有来自追溯的源文件路径,这将使调试更加困难。