gpt4 book ai didi

python-3.x - 如何让 Python "import.util.module_from_spec"更像 "import"”?

转载 作者:行者123 更新时间:2023-12-04 13:06:55 24 4
gpt4 key购买 nike

我正在继续 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
如何使用 importlib.util 获得相同的行为?
(但我应该注意,对于 sys ,两者都可以找到“路径”子模块作为 sys 的属性。)

最佳答案

该模块是否曾经执行过?如果不是,则模块内的赋值或声明尚未将子对象放入 __dir__模块对象。从标准文件加载器中此函数的版本开始,当您调用 module_from_spec 时你得到的只是模块,以及逻辑上属于所有模块的成员。它没有内容。
(系统可能会在不同的路径上加载模块或与其他 Loader 对象处于不同的使用状态,这可能会使整个任务复杂化。例如,对于 sys.path,您获得的模块似乎已经被填充。​​请记住,有出于某种原因,这里是一个子对象。不仅仅是一个 Python 加载器。)
如果尚未加载,要填充模块对象,您将调用

module_spec.loader.exec_module(module)
(如果存在。)
例如在 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)
将输出:
<function fill at 0x7fae70e6fd90>
在旧版本的 Python 中, exec_module丢失,您需要调用:
module_spec.loader.load_module(module.__name__)
但是,在 3.6 及更高版本上,上面的代码按预期工作。
通过查看 importlib._bootstrap.py::_exec 收集到的信息,以及它调用的东西。
这里仍然存在一个问题,即加载模块中的导入最终会出现在全局命名空间中还是您自己的命名空间中。但这是另一个问题。

关于python-3.x - 如何让 Python "import.util.module_from_spec"更像 "import"”?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69005998/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com