“导入”更喜欢什么-.pyd(.so)或.py?

时间:2019-11-04 02:21:57

标签: python python-3.x windows python-import

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

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

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

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

同一问题也适用于Unix Python扩展名(.so)

2 个答案:

答案 0 :(得分:6)

在典型的Python安装中,ExtensionFileLoader类优先于用于.py文件的SourceFileLoaderExtensionFileLoader处理.pyd文件的导入,在Windows计算机上,您会发现.pyd已在importlib.machinery.EXTENSION_SUFFIXES中注册(注意:在Linux / macOS上它将有{{ 1}})。

因此,在同一目录中发生名称冲突的情况下(按顺序浏览.so时,这意味着“领带”),sys.path文件优先于a.pyd文件。您可以验证在创建空的a.pya.pyd文件时,语句a.py会尝试加载DLL(当然会失败)。

要查看CPython源代码中的优先级,请查看here in importlib._bootstrap_external. _get_supported_file_loaders

import a

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

  

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

     

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

     

(提示:搜索顺序由函数imp.get_suffixes()返回的后缀列表确定。通常按以下顺序搜索后缀:“ .so”,“ module.so”,“。py “,”。pyc“。目录不会显式出现在此列表中,而是位于其中的所有条目之前。)

此文档未明确提及“ .pyd”,但在Windows中等效于“ .so”。我刚刚在Windows计算机上进行了测试,实际上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! 出现在后缀列表中'.pyd'之前。

请注意,以上给出的参考文献很旧!自从撰写本文以来,导入系统已得到全面改进,并且为用户提供了底层机制(例如,您可以更改sys.meta_path来注册自己的加载程序或更改优先级)。因此,现在可以自定义“ .py”而不是“ .pyd”,'.py'对任何内容说什么都没关系(实际上,该功能现在已被弃用)。当然,默认的Python安装不会这样做,并且默认优先级与上面的参考文献相同。

答案 1 :(得分:1)

感谢wim的回答。

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

显示结果

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

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

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