【问题标题】:Remove several lines from the top of a traceback从回溯顶部删除几行
【发布时间】:2017-08-19 12:03:03
【问题描述】:

我正在调用importlib.import_module("somemodulename") 来导入一些自定义的用户定义模块。此导入可能会失败。我想向用户提供有关失败原因的信息,因此我需要打印回溯,但它往往很长,充满了来自importlib 模块的行。例如它是:

Traceback (most recent call last):
  File "C:\abc\cde\efg\importer.py", line 101, in load
    self.__module = importlib.import_module(self.__name)
  File "C:\Programming\Python36-32\lib\importlib\__init__.py", line 126, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 978, in _gcd_import
  File "<frozen importlib._bootstrap>", line 961, in _find_and_load
  File "<frozen importlib._bootstrap>", line 950, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 655, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 678, in exec_module
  File "<frozen importlib._bootstrap>", line 205, in _call_with_frames_removed
  File "C:\abc\cde\efg\modules\testerror.py", line 3, in <module>
    x = 1 / 0  # intentional error for module testing purposes
ZeroDivisionError: division by zero

显然大多数行对用户没有兴趣。我希望回溯看起来像这样:

Traceback (most recent call last):
  File "C:\abc\cde\efg\modules\testerror.py", line 3, in <module>
    x = 1 / 0  # intentional error for module testing purposes
ZeroDivisionError: division by zero

但问题是我不能依赖从 importlib 包生成的行数(这是一个实现细节,可能会在未来版本中更改,可能是平台或 Python 安装特定的),我想跳过,关于自定义模块生成的行数错误(他可以自己导入一些其他模块,可能会导致错误),我想保留。更复杂的是,用户还可以调用importlib 模块函数,这在这种情况下很好,应该包含在回溯中。

换句话说,我需要从回溯中删除所有importlib 错误行的第一块。除了以某种“聪明”的方式解析回溯行之外的任何想法,我认为这将是一个依赖于importlib 包中太多实现细节的黑客且非常脆弱的解决方案?

注意:我使用的是 Python 3.5+,解决方案应该与平台无关

【问题讨论】:

标签: python python-3.x traceback python-importlib


【解决方案1】:

好的,我深入研究了tracebackimportlib 模块,我想我已经找到了解决方案。这似乎适用于普通 Python 文件中的模块。但是不确定冷冻包、压缩包等。需要针对这些场景进行更多测试。

import importlib
import sys
import traceback

moduleName = "somepackage.somemodule"
try:
   importlib.import_module(moduleName)
except Exception:
    spec = importlib.util.find_spec(moduleToImport)
    if spec is None:
        # if the module is not found, then do not print traceback at all
        count = 0
    else:
        fileName = spec.loader.get_filename()
        extracts = traceback.extract_tb(sys.exc_info()[2])
        count = len(extracts)
        # find the first occurrence of the module file name
        for i, extract in enumerate(extracts):
            if extract[0] == fileName:
                break
            count -= 1
    # keep only the count of last lines
    print(traceback.format_exc(limit=-count))

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-10-25
    • 2020-01-23
    • 2017-02-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多