import sys
from importlib.machinery import ModuleSpec
import inspect
def trace(*args, **kwargs):
t = inspect.stack()[1];
print(f'\t{t.lineno}:{t.function:16} {args}, {kwargs}')
class MyFinder:
@classmethod
def find_spec(self, fullname, path=None, target=None): # line 17
# 先找到模块,要返回相应的loader, loader也可以是本类
trace(fullname, path, target)
return ModuleSpec(fullname, MyLoader())
class MyLoader:
def create_module(self, spec):
trace(spec)
module = type(sys)(spec.name)
# 一定要加到sys.modules, 否则子模块无法查找
sys.modules[spec.name] = module
# 如果要一个模块,按python规范,要添加__path__属性
module.__path__ = 'path for ' + spec.name
return module
def exec_module(self, module):
trace(module)
# 可以给 模块中添加变量
module.__dict__['@self'] = module
module.__dict__['name'] = module.__name__
# 注册自动加载钩子
mp = sys.meta_path
mp.append(MyFinder)
# 执行导入
# 先调用 finder.find_spec()
# 再调用 spec.create_module(), spec.exec_module()
import fac.ef
print(fac.__dict__)
print(fac.ef.__dict__)
print(fac.name)
print(fac.ef.name)
17:find_spec ('fac', None, None), {}
24:create_module (ModuleSpec(name='fac', loader=<__main__.MyLoader object at 0x00000161F7B09B50>),), {}
34:exec_module (<module 'fac' (<__main__.MyLoader object at 0x00000161F7B09B50>)>,), {}
17:find_spec ('fac.ef', 'path for fac', None), {}
24:create_module (ModuleSpec(name='fac.ef', loader=<__main__.MyLoader object at 0x00000161F7A869A0>),), {}
34:exec_module (<module 'fac.ef' (<__main__.MyLoader object at 0x00000161F7A869A0>)>,), {}
{'__name__': 'fac', '__doc__': None, '__package__': '', '__loader__': <__main__.MyLoader object at 0x00000161F7B09B50>, '__spec__': ModuleSpec(name='fac', loader=<__main__.MyLoader object at 0x00000161F7B09B50>), '__path__': 'path for fac', '@self': <module 'fac' (<__main__.MyLoader object at 0x00000161F7B09B50>)>, 'name': 'fac', 'ef': <module 'fac.ef' (<__main__.MyLoader object at 0x00000161F7A869A0>)>}
{'__name__': 'fac.ef', '__doc__': None, '__package__': 'fac', '__loader__': <__main__.MyLoader object at 0x00000161F7A869A0>, '__spec__': ModuleSpec(name='fac.ef', loader=<__main__.MyLoader object at 0x00000161F7A869A0>), '__path__': 'path for fac.ef', '@self': <module 'fac.ef' (<__main__.MyLoader object at 0x00000161F7A869A0>)>, 'name': 'fac.ef'}
fac
fac.ef