__import__ in Python
Table of Contents
It’s known that Python’s import
statement is implemented by __import__
function. In general, if we want to import a module dynamically, we can use import_module
function, which is a wrapper around __import__
.
The most important difference between these two functions is that import_module() returns the specified package or module (e.g. pkg.mod), while import() returns the top-level package or module (e.g. pkg). – https://docs.python.org/3/library/importlib.html#importlib.import_module
import itertools
and from requests import exceptions
can be translated to:
import importlib
itertools = importlib.import_module('itertools')
exceptions = importlib.import_module('requests.exceptions')
__import__
#
This is an advanced function that is not needed in everyday Python programming, unlike importlib.import_module()
.
Here is an example of how __import__
is called:
old_import = __import__
def noisy_importer(name, globals=None, locals=None, fromlist=None, level=0):
print(f'name: {name!r}')
print(f'fromlist: {fromlist}')
print(f'level: {level}')
print('-' * 80)
return old_import(name, locals, globals, fromlist, level)
import builtins
builtins.__import__ = noisy_importer
print('import math')
import math
print('from math import sqrt')
from math import sqrt
>>>
import math
name: 'math'
fromlist: None
level: 0
--------------------------------------------------------------------------------
from math import sqrt
name: 'math'
fromlist: ('sqrt',)
level: 0
--------------------------------------------------------------------------------
As we mentioned earlier, the __import__
returns the top level module.
For example, requests=__import('requests.exceptions',globals(),locals(),[],0)
. If you want to get the submodule exceptions
, you need to use getattr
: equests_exceptions=getattr(__import__('requests', globals(), locals(), [], 0), 'exceptions')
.
There is another tricky way to import the submodule: use a non-empty fromlist
: requests_exceptions = __import__('requests.exceptions', globals(), locals(), [None], 0)
.
Additionally, we can also set fromlist
to specify the names of submodules that should be imported. The statement from spam.ham import eggs, sausage as saus
can be translated to
_temp = __import__('spam.ham', globals(), locals(), ['eggs', 'sausage'], 0)
eggs = _temp.eggs
saus = _temp.sausage
Skip importing non-existing modules with __import__
#
This a use case of the __import__
function. Some packages are missing, but we want to make sure that the code does not crash when importing them.
import builtins
from unittest.mock import Mock
old_import = __import__
def skip_imports(name, globals=None, locals=None, fromlist=None, level=0):
skip_list = {'urllib3', 'requests_oauthlib', 'cryptography'}
if name in skip_list or any(name.startswith(f'{p}.') for p in skip_list):
return Mock()
else:
return old_import(name, globals, locals, fromlist, level)
builtins.__import__ = skip_imports