How do I dynamically import a module similar to the "import X from Y" syntax in Python?

3.3k Views Asked by At

I'm trying to achieve:

from X import Y

where Y is a string name of a module that is only known during runtime.

I've tried using

module = importlib.import_module(Y, X)

But that doesn't work. I also don't know the path of the module as it only exists during runtime within the module Brownie and is deleted afterward.

Would very much appreciate help.

2

There are 2 best solutions below

2
On BEST ANSWER

You almost got it, except that the second argument to import_module is the package name, not the attribute you want. When you want a attribute from a module, you must run the code for the entire module first, since python has no way to predict which lines will have side effects ahead of time.

So first you import the module:

X = importlib.import_module('X')

Then you need to get the attribute from the module:

Y = getattr(module, 'Y')

Of course you probably don't want to create the temprorary variable X, so you can do

Y = getattr(importlib.import_module('X'), 'Y')
0
On

Sometimes I use the pydoc.locate function to achieve the same. Mainly as it allows safe importing of any python entity including modules.

Oddly I struggle to find the documentation - The online article does not mention it (pydoc for reference), but it however it does exist in the source: https://github.com/python/cpython/blob/3.10/Lib/pydoc.py#L1714


Luckily it's very easy to use:

>>> from pydoc import locate
>>> locate('django')
<module 'django' from '\\env\\lib\\site-packages\\django\\__init__.py'>

It can import anything such as a module through a parent module.

>>> locate('short.views.base')
<module 'short.views.base' from 'short\\views\\base.py'>

A class from a module:

>>> locate('short.views.base.ShortMixin')
<class 'short.views.base.ShortMixin'>

Native modules or through local references:

>>> locate('os')
<module 'os' from '\\Python\\Python38\\lib\\os.py'>
>>> locate('.')
<module 'builtins' (built-in)>
>>> locate('globals')
<built-in function globals>

Or a function - even local import and unbound function from a class within the target module:

>>> locate('short.views.base.ShortMixin.get_template_names')
<function ShortMixin.get_template_names at 0x0000000003C3C160>