2016-12-19 16 views
1

Я пытаюсь использовать модуль самоанализа Python inspect для извлечения исходного кода для живых объектов, которые были загружены в область с использованием функции module_from_specimportlib.util. Попытки использования inspect.getsource() либо самого spec_file, либо любой функции из файла спецификации успешно возвращают желаемый исходный код. Тем не менее, тот же метод, который использовался для извлечения исходного кода для типов классов в файле спецификации, вызывает значение TypeError: None is a built-in class.Исходная информация отсутствует в классах python, загруженных модулем_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?')