I am trying to use Python's introspection module inspect
to retrieve the source code for live objects which have been loaded into the scope using the module_from_spec
function of importlib.util
. Attempts to use inspect.getsource()
on either the spec_file itself or any function in the spec file successfully return the desired source code. However, the same method used to retrieve the source code for class types in the spec file throws a TypeError: None is a built-in class
.
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?')
The culprit seems to be the inspect.getfile()
call in the traceback chain where function objects return object.__code__
while class objects attempt to load their module in order to retrieve the module.__file__
. Why do functions have the __code__
method, while classes do not? Is this a side-effect of how Python handles types which inadvertently breaks introspection for dynamically loaded classes?
It looks like the loaded module must be added to
sys.modules
in order for the source and module path to be correctly reflected in classes (though I am unable to find reference to this in the documentation). So, if you importsys
and add your module tosys.modules
, your example should work (I tested a similar example with Python 3.5):