Dmitry Vyal
Dmitry Vyal

Reputation: 2427

How to get a path for a module imported by importlib, where a class was defined

There is a nice way to get a path for a module where a class was defined, just do

inspect.getfile(obj.__class__)

Unfortunately, it seems to break down for files loaded by importlib:

spec = importlib.util.spec_from_file_location('loaded_module', module_path)
M = importlib.util.module_from_spec(spec)
spec.loader.exec_module(M)

obj = M.MyClass()
inspect.getfile(obj.__class__)

results in

  File "/nix/store/z65l1jqvxa58zzwwa3bvglb6asj4y8cv-python3-3.8.5/lib/python3.8/inspect.py", line 665, in getfile
    raise TypeError('{!r} is a built-in class'.format(object))
TypeError: <class 'loaded_module.MyClass'> is a built-in class

Any ideas how to fix this?

Upvotes: 1

Views: 621

Answers (1)

anthony sottile
anthony sottile

Reputation: 69844

The expectation of inspect.getfile is that the class object (which has a string __module__ attribute which is the module name) has its module in sys.modules (where a module can be looked up by name)

without the module in sys.modules it cannot use that chain to find your file

to put it into sys.modules you'd do something like:

sys.modules[M.__name__] = M

but if you have access to the M object somewhere, you can access .__file__ directly, or if you have access to the loader

alternatively, if you know some method is defined on the class in that file, you can interrogate the code object of that function:

>>> M.C.__init__.__code__.co_filename
t.py

Upvotes: 1

Related Questions