roc*_*cky 5 python-import python-3.x python-importlib
我正在继续 Ned Batchelder 的 byterun 代码,这是一个用 Python 编写的 Python 解释器,适用于 Python 3.4 以外的 Python 版本。请参阅x-python。
这种方法的长期关注点之一是将导入中的解释器命名空间与解释的程序命名空间分开。
旁白:如果您想要不解释为导入模块的快速解释器,那么不分离命名空间可能是有利的,但是分离模块更正确,尽管速度较慢,并且在解释来自不同 Python 版本的字节码时是必要的。
因此,当解释器遇到IMPORT_NAME操作码时,我想importlib.util基本上拥有一个与解释器遇到的任何导入不同的模块副本。
我现在遇到的问题是这些导入方式不同,这可以使用hasattr().
这是一个例子:
import importlib
module_spec = importlib.util.find_spec("textwrap")
textwrap_module = importlib.util.module_from_spec(module_spec)
submodule = "fill"
print(hasattr(textwrap_module, submodule)) # False
import textwrap
print(hasattr(textwrap, submodule)) # True
Run Code Online (Sandbox Code Playgroud)
我如何使用 获得相同的行为importlib.util?
(但是我应该注意,对于sys,两者都可以找到“path”子模块作为 的属性sys。)
该模块是否被执行过?如果不是,则模块内的赋值或声明尚未将子对象放入__dir__模块对象中。从标准文件加载器中该函数的版本来看,当您调用时,module_from_spec您得到的只是模块以及逻辑上属于所有模块的成员。它没有内容。
(系统可能会在不同的路径上或与其他 Loader 对象一起使用不同的状态下加载模块,这可能会使整个任务变得复杂。例如sys.path,您获得的模块似乎已经填充了。请记住,有一个子-object 在这里是有原因的。Python 加载器不只是一个。)
如果尚未加载,要填充模块对象,您可以调用
module_spec.loader.exec_module(module)
Run Code Online (Sandbox Code Playgroud)
(如果存在的话。)
以 Python 3.8 为例:
import importlib
module_spec = importlib.util.find_spec('textwrap')
module = importlib.util.module_from_spec(module_spec)
module_spec.loader.exec_module(module)
print(module.fill)
Run Code Online (Sandbox Code Playgroud)
将输出:
<function fill at 0x7fae70e6fd90>
Run Code Online (Sandbox Code Playgroud)
在旧版本的Python中,exec_module缺少,你需要调用:
module_spec.loader.load_module(module.__name__)
Run Code Online (Sandbox Code Playgroud)
然而,在 3.6 及更高版本上,上面的代码可以按预期工作。
这些信息是通过查看 importlib._bootstrap.py::_exec及其所调用的内容来收集的。
这里仍然存在一个问题,即加载的模块内的导入最终会出现在全局命名空间还是您自己的命名空间中。但这是另一个问题。
| 归档时间: |
|
| 查看次数: |
7960 次 |
| 最近记录: |