Reputation: 67
I want to get all the modules imported from an arbitrary module m
.
When m
imports a module in the following way:
from a.b import c
or:
import a.b.c as c
(where a
and b
are packages, and c
is a module)
The result of dir(m)
would contain c
(among other things).
However, when I use:
import a.b.c
The result of dir(m)
would contain a
, and not c
.
I also tried iterating over sys._getframe(1).f_locals.items()
after importing m
, but got the same result.
How can I, having the object of m
that imports c
that way, know that it actually imported c
?
Upvotes: 0
Views: 158
Reputation: 43256
You can use the ast
module to parse the module's source code and extract imports:
import sys
import ast
import inspect
def find_imports(module):
code = inspect.getsource(module)
tree = ast.parse(code)
imports = set()
for node in ast.walk(tree):
if isinstance(node, ast.Import):
imports.update(alias.name for alias in node.names)
elif isinstance(node, ast.ImportFrom):
imports.add(node.module)
for alias in node.names:
module_name = '{}.{}'.format(node.module, alias.name)
if module_name in sys.modules:
imports.add(module_name)
return imports
Keep in mind that this only works if the module's source is available as plain python code.
As an example, consider this module:
from os.path import isfile
from importlib import util
import urllib.request as urlquest
import urllib.parse
import sys
The output for this module would be
{'sys', 'urllib.request', 'os.path', 'importlib', 'importlib.util', 'urllib.parse'}
from module import submodule
, "module.submodule"
will appear in the output. However, if the code performs an import like from module import non_module
, only "module"
will appear in the output.Upvotes: 3