"import"更喜欢什么 - .pyd (.so) 还是.py?



我在同一目录中有两个文件,一个编译的库文件和源文件:

.
├── a.py
└── a.pyd

看起来像是import a实际导入了a.pyd模块。但我找不到任何官方文件来保证这一点。

有人知道不同文件类型的导入顺序吗?

这个问题同样适用于Unix Python扩展(.so(

在典型的Python安装中,ExtensionFileLoader类的优先级高于用于.py文件的SourceFileLoader。它是处理.pyd文件导入的ExtensionFileLoader,在Windows机器上,你会发现.pydimportlib.machinery.EXTENSION_SUFFIXES中注册(注意:在Linux/macOS上,它会在那里有.so(。

因此,在同一目录内发生名称冲突的情况下(按顺序查看sys.path时意味着"平局"(,a.pyd文件优先于a.py文件。您可以验证在创建空的a.pyda.py文件时,语句import a是否尝试加载DLL(当然会失败(。

要查看CPython源中的优先级,请查看importlib._bootstrap_external. _get_supported_file_loaders:中的此处

def _get_supported_file_loaders():
"""Returns a list of file-based module loaders.
Each item is a tuple (loader, suffixes).
"""
extensions = ExtensionFileLoader, _imp.extension_suffixes()
source = SourceFileLoader, SOURCE_SUFFIXES
bytecode = SourcelessFileLoader, BYTECODE_SUFFIXES
return [extensions, source, bytecode]  # <-- extensions before source!

有关文档参考,请参阅http://www.python.org/doc/essays/packages/

如果我有一个同名的模块和一个包怎么办

您可能有一个目录(在sys.path上(,其中既有模块spam.py,也有包含_init_.py的子目录spam(如果没有_init_.py,目录将不会被识别为包(。在这种情况下,子目录具有优先级,导入垃圾邮件将忽略spam.py文件,而加载包垃圾邮件。如果您希望模块spam.py具有优先级,则必须将其放置在sys.path.中较早的目录中

(提示:搜索顺序由函数imp.get_suffixes((返回的后缀列表决定。通常按以下顺序搜索后缀:"。因此"模块.so"&";。py"&";。pyc">。目录没有明确地出现在这个列表中,但在其中的所有条目之前。(

此文档没有明确提到"。pyd";,但这相当于Windows中的";。所以";。我刚刚在Windows机器上进行了测试,实际上'.pyd'出现在后缀列表中的'.py'之前。

请注意,上面给出的参考文献非常古老!自从写了这篇文章以来,导入系统已经进行了彻底的改进,底层机制已经公开供用户访问:例如,您可以更改sys.meta_path来注册自己的加载程序或更改优先级。因此,现在可以自定义".py"而不是".pyd",而且imp.get_suffixes()对任何事情都有什么看法并不重要(实际上,该函数现在已被弃用(。当然,默认的Python安装不会做到这一点,默认的优先级与上面提到的参考相同。

感谢wim的回答。

import importlib.util
print(importlib.util.find_spec('a'))

显示结果

ModuleSpec(name='a', loader=<_frozen_importlib_external.ExtensionFileLoader object at 0x02A79EF0>, origin='a.pyd')

尽管我看不出pyd的顺序,py。

至少我可以区分我导入模块化的是哪一个。

相关内容

最新更新