Python sys.meta_path[1] 冻结的导入器。应用程序是不是曾经使用过它?

Posted

技术标签:

【中文标题】Python sys.meta_path[1] 冻结的导入器。应用程序是不是曾经使用过它?【英文标题】:Python sys.meta_path[1] the frozen importer. Does an application ever use it?Python sys.meta_path[1] 冻结的导入器。应用程序是否曾经使用过它? 【发布时间】:2022-01-15 22:33:39 【问题描述】:

我已经相当深入地研究了 --import--()、sys.meta_path[] 和 sys.path_hooks[]

事实上,我正在编写一个导入器上下文管理器来管理相对导入。

在标准 Python(到 3.10)中有 3 个元路径,如下所示。当然,目的是您可以编写自己的 meta_path 查找器并将它们附加到 sys.meta_path 我这样做。

顺便说一句,sys.meta_path 中的一个条目应该实现一个方法 find_spec(),它返回一个“导入规范”,可以很容易地转换成一个模块

>>> sys.meta_path
[<class '_frozen_importlib.BuiltinImporter'>, <class 
'_frozen_importlib.FrozenImporter'>, <class '_frozen_importlib_external.PathFinder'>]

0 'BuiltinImporter' 为您提供诸如 sys 和 math 等内置模块,这些模块当然不是在 Python 中实现的,而是 VM 的一部分。

2 'PathFinder' 从 sys.path 获取内容,包括库内容(os、re、enum),例如'/usr/lib/python3.10'

2 获取您的应用程序导入。

顺便说一句,meta_path[2] 使用 sys.path_hooks[1] 为您的应用程序导入获取查找器,但在获取库导入时似乎不需要任何帮助。除非您直接从 zip 库导入,否则我猜 sys.path_hooks[0] 最终会使用 zip finder。

1 'FrozenImporter' 显然是导入引导程序的一部分。

导入机制本身是用 Python 实现的,所以肯定是先有鸡还是先有蛋。我猜VM以某种方式使用它来使导入成为可能。 Frozen 意味着它被预编译成 .pyc,我还读到如果冻结的文件以某种方式丢失 importlib 可以从较慢的 Python 源引导。

通过装饰“--import--()”、“sys.meta_path”和“sys.path_hooks”,我可以看到它们的交互。

但是 sys.meta_path[1] 'FrozenImporter' 似乎从来没有做任何事情。如果我导入“importlib”,则不会运行 meta_path,因为 importlib 已经在 sys.modules 中

如果我检查 sys.modules 中的“os”和“importlib”,我可以看到它们都使用相同的加载器。

>>> import os
>>> type(sys.modules['os'].__spec__.loader)
<class '_frozen_importlib_external.SourceFileLoader'>
>>> type(sys.modules['importlib'].__spec__.loader)
<class '_frozen_importlib_external.SourceFileLoader'>

好的,我的问题是应用程序可以通过什么方式使用 sys.meta_path[1]?

我想知道以确保我的导入 shim 支持该用例。

【问题讨论】:

【参考方案1】:

实际上我已经设法让 meta_path[1] 着火了

del sys.modules['_frozen_importlib']
del sys.modules['importlib']
import importlib

通过我所有的装饰器产生了以下摘录:

pre  __import__("_frozen_importlib") mod: "importlib" fl: None level: "0" path: "['/usr/lib/python3.10/importlib']"
pre  meta_path[0] arg0 "_frozen_importlib"
post meta_path[0] arg0 "_frozen_importlib" result "None"
pre  meta_path[1] arg0 "_frozen_importlib"
post meta_path[1] arg0 "_frozen_importlib" result "ModuleSpec(name='_frozen_importlib', loader=<class '_frozen_importlib.FrozenImporter'>, origin='frozen')"
post __import__("_frozen_importlib") mod: "importlib" fl: None level: "0" path: "['/usr/lib/python3.10/importlib']" result: "<module '_frozen_importlib' (frozen)>"

上面的倒数第二行显示 meta_path[1] 返回 _frozen_importlib 的规范。

使用--import 完成--为 importlib 完成导入 _frozen_importlib

以防万一有人感兴趣,一切以

开头
pre  __import__("importlib") mod: "__main__" fl: None level: "0" path: ""
pre  meta_path[0] arg0 "importlib"
post meta_path[0] arg0 "importlib" result "None"
pre  meta_path[1] arg0 "importlib"
post meta_path[1] arg0 "importlib" result "None"
pre  meta_path[2] arg0 "importlib"
pre  path_hook[0] arg0 "/proj/software/shareware"
ex   path_hook[0] arg0 "/proj/software/shareware" ex "<class 'zipimport.ZipImportError'>" "not a Zip file"
post path_hook[0] arg0 "/proj/software/shareware" result "None"
pre  path_hook[1] arg0 "/proj/software/shareware"
post path_hook[1] arg0 "/proj/software/shareware" result "FileFinder('/proj/software/shareware')"
post meta_path[2] arg0 "importlib" result "ModuleSpec(name='importlib', loader=<_frozen_importlib_external.SourceFileLoader object at 0x7f2b72667640>, origin='/usr/lib/python3.10/importlib/__init__.py', submodule_search_locations=['/usr/lib/python3.10/importlib'])"

显示 meta_path[2] 使用 path_hook[1] 查找 'importlib'

【讨论】:

以上是关于Python sys.meta_path[1] 冻结的导入器。应用程序是不是曾经使用过它?的主要内容,如果未能解决你的问题,请参考以下文章

黑苹果冻屏死机鼠标能动

[洛谷 P3787] 冰精冻西瓜

冰精冻西瓜[P3787洛谷]

[luogu U8984][新创无际夏日公开赛] 冰精冻西瓜 [树状数组]

luogu P3787 冰精冻西瓜

Robin8 Blockchain Summit脑冻记者前线直击