2017-08-19 100 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))