seitime-frappe/frappe/utils/lazy_loader.py
2021-03-09 11:59:17 +05:30

34 lines
1 KiB
Python

import importlib.util
import sys
def lazy_import(name, package=None):
"""Import a module lazily.
The module is loaded when modules's attribute is accessed for the first time.
This works with both absolute and relative imports.
$ cat mod.py
print("Loading mod.py")
$ python -i lazy_loader.py
>>> mod = lazy_import("mod") # Module is not loaded
>>> mod.__str__() # module is loaded on accessing attribute
Loading mod.py
"<module 'mod' from '.../frappe/utils/mod.py'>"
>>>
Code based on https://github.com/python/cpython/blob/master/Doc/library/importlib.rst#implementing-lazy-imports.
"""
# Return if the module already loaded
if name in sys.modules:
return sys.modules[name]
# Find the spec if not loaded
spec = importlib.util.find_spec(name, package)
if not spec:
raise ImportError(f'Module {name} Not found.')
loader = importlib.util.LazyLoader(spec.loader)
spec.loader = loader
module = importlib.util.module_from_spec(spec)
sys.modules[name] = module
loader.exec_module(module)
return module