2017-08-19 45 views
0

我打电话给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模块功能,在这种情况下这很好,应该包含在回溯中。

换句话说,我需要摆脱traceback的所有第一块importlib错误行。除了以某种'聪明'的方式解析回溯线以外的任何想法,我认为这将是一个依靠importlib包中的太多实现细节的骇人而脆弱的解决方案?

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

+0

查看['traceback'](https://docs.python.org/3/library/traceback.html)模块。 – direprobs

回答

0

OK,我更深入地挖掘了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))