2016-12-19 34 views
1

我想用Python的自檢模塊inspect來檢索已使用函數函數importlib.util加載到作用域中的活動對象的源代碼。試圖在spec_file本身或spec文件中的任何函數上使用inspect.getsource()成功返回所需的源代碼。但是,用於檢索spec文件中類類型的源代碼的相同方法會拋出TypeError: None is a built-in classpython類中加載的module_from_spec中缺少源文件信息

from importlib.util import spec_from_file_location, module_from_spec 
spec_file = spec_from_file_location("file_module", 'test_file.py') 
spec_module = module_from_spec(spec_file) 
spec_file.loader.exec_module(spec_module) 

# spec module 
import inspect 
assert isinstance(inspect.getsource(spec_module), str) 

# function in spec module 
func_obj = getattr(spec_module, 'test_function') 
assert isinstance(inspect.getsource(func_obj), str) 

# class in spec module 
class_obj = getattr(spec_module, 'testClass') 
try: 
    inspect.getsource(class_obj) 
except TypeError: 
    print('where did the source code data go?') 

的罪魁禍首似乎是在追溯鏈,其中的函數對象返回對象inspect.getfile()通話。 __code__而類對象嘗試加載其模塊以檢索模塊。 __file__。爲什麼函數有__code__方法,而類沒有?這是Python處理類型的一個副作用,它會無意中破壞動態加載類的內省?

回答

0

它看起來像加載模塊必須被添加到sys.modules爲了源和模塊路徑正確地反映在類中(雖然我無法在文檔中找到對此的參考)。所以,如果你輸入sys和你的模塊添加到sys.modules,你的例子應該工作(我測試與Python 3.5類似的例子):

import sys 

from importlib.util import spec_from_file_location, module_from_spec 
spec_file = spec_from_file_location("file_module", 'test_file.py') 
spec_module = module_from_spec(spec_file) 
spec_file.loader.exec_module(spec_module) 

sys.modules['file_module'] = spec_module 

# spec module 
import inspect 
assert isinstance(inspect.getsource(spec_module), str) 

# function in spec module 
func_obj = getattr(spec_module, 'test_function') 
assert isinstance(inspect.getsource(func_obj), str) 

# class in spec module 
class_obj = getattr(spec_module, 'testClass') 
try: 
    inspect.getsource(class_obj) # This should work now 
except TypeError: 
    print('where did the source code data go?')