我正在创建一个Python模块,将不同语言/框架提供的API映射到Python.理想情况下,我希望将其作为单个根包提供,该包公开辅助方法,并将该其他框架中的所有命名空间映射到Python包/模块.为方便起见,我们以CLR为例:
import clr.System.Data
import clr.System.Windows.Forms
Run Code Online (Sandbox Code Playgroud)
这clr是一个神奇的顶层包,它暴露了CLR命名空间System.Data和System.Windows.Forms子包/子模块(据我所知,一个包只是一个带有子模块/包的模块;它在其中有其他类型的成员仍然有效).
我已经阅读了PEP-302并编写了一个简单的原型程序,通过安装自定义meta_path钩子实现了类似的效果.该clr模块本身是一个适当的Python模块其中,导入时,套__path__ = [](使其成为一个包,以便import甚至试图为子模块在所有查找),并注册该钩.钩子本身拦截包的全名开始的任何包加载,使用"clr."动态创建新模块imp.new_module(),将其注册sys.modules,并使用pixie dust和rainbows用原始API中的类和方法填充它.这是代码:
import sys
import imp
class MyLoader:
def load_module(self, fullname):
try:
return sys.modules[fullname]
except KeyError:
pass
print("--- load ---")
print(fullname)
m = imp.new_module(fullname)
m.__file__ = "clr:" + fullname
m.__path__ = []
m.__loader__ = self
m.speak = lambda: print("I'm " + fullname)
sys.modules.setdefault(fullname, m)
return m
class MyFinder:
def …Run Code Online (Sandbox Code Playgroud) 我希望下面的问题不会太长。但除此之外,我无法通过问题和我想要的来解释:
从如何使用 importlib 从任意来源导入模块中学习?(我昨天的问题)我为新文件类型 (.xxx) 编写了一个特定的加载程序。(实际上 xxx 是 pyc 的加密版本,以防止代码被盗)。
我只想为新文件类型“xxx”添加一个导入挂钩,而不会以任何方式影响其他类型(.py、.pyc、.pyd)。
现在,加载器是ModuleLoader,继承自mportlib.machinery.SourcelessFileLoader.
使用sys.path_hooksloader 应添加一个钩子:
myFinder = importlib.machinery.FileFinder
loader_details = (ModuleLoader, ['.xxx'])
sys.path_hooks.append(myFinder.path_hook(loader_details))
Run Code Online (Sandbox Code Playgroud)
注意:这是通过调用激活一次 modloader.activateLoader()
加载名为test(这是一个test.xxx)的模块后,我得到:
myFinder = importlib.machinery.FileFinder
loader_details = (ModuleLoader, ['.xxx'])
sys.path_hooks.append(myFinder.path_hook(loader_details))
Run Code Online (Sandbox Code Playgroud)
但是,当我sys.path_hooks在添加钩子之前删除内容时:
sys.path_hooks = []
sys.path.insert(0, '.') # current directory
sys.path_hooks.append(myFinder.path_hook(loader_details))
Run Code Online (Sandbox Code Playgroud)
有用:
>>> modloader.activateLoader()
>>> import test
using xxx class
in xxxLoader exec_module
in xxxLoader get_code: .\test.xxx
ANALYZING ...
GENERATE …Run Code Online (Sandbox Code Playgroud)