“导入"是什么意思更喜欢 - .pyd (.so) 还是 .py? [英] What does "import" prefer - .pyd (.so) or .py?

查看:59
本文介绍了“导入"是什么意思更喜欢 - .pyd (.so) 还是 .py?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

<预><代码>.├── a.py└── a.pyd

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

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

同样的问题适用于 Unix Python 扩展 (.so)

解决方案

在典型的 Python 安装中,ExtensionFileLoader 类优先于 SourceFileLoader 用于 .py 文件.它是处理 .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():"返回基于文件的模块加载器列表.每个项目都是一个元组(加载程序,后缀)."extensions = ExtensionFileLoader, _imp.extension_suffixes()source = SourceFileLoader, SOURCE_SUFFIXES字节码 = SourcelessFileLoader, BYTECODE_SUFFIXESreturn [extensions, source, bytecode] # <-- 扩展源之前!

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

<块引用>

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

<块引用>

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

(提示:搜索顺序由函数imp.get_suffixes()返回的后缀列表决定.通常按以下顺序搜索后缀:.so"、module.so";、.py"、.pyc".目录并未明确出现在此列表中,而是位于其中的所有条目之前.)

该文档没有明确提及.pyd",但它是.so"的 Windows 等价物.我刚刚在 Windows 机器上测试过,确实 '.pyd' 出现在后缀列表中的 '.py' 之前.

请注意,上面给出的参考文献很旧!自从写这篇文章以来,导入系统已经被彻底改造,并且底层机制已经暴露给用户访问:你可以改变 sys.meta_path 来注册您自己的加载程序或更改优先级.因此,现在可以自定义 '.py' 优先于 '.pyd',并且 imp.get_suffixes() 对任何事情所说的都无关紧要(实际上,该功能现已弃用).当然,默认的 Python 安装不会这样做,并且默认优先级保持与上面提到的参考相同.

I have 2 files in same directory, a compiled library file and source file:

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

It looks like import a that actually imports the a.pyd module. But I can't find some official document guaranteeing that.

Does any one know about the import ordering of different file type?

This same question applies to Unix Python extensions (.so)

解决方案

In a typical Python installation, the ExtensionFileLoader class has precedence over the SourceFileLoader that is used for .py files. It's the ExtensionFileLoader which handles imports of .pyd files, and on a Windows machine you will find .pyd registered in importlib.machinery.EXTENSION_SUFFIXES (note: on Linux/macOS it will have .so in there instead).

So in the case of name collision within same directory (which means a "tie" when looking through sys.path in order), the a.pyd file takes precedence over the a.py file. You may verify that when creating empty a.pyd and a.py files, the statement import a attempts the DLL load (and fails, of course).

To see the precedence in the CPython sources, look here in 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!

For a doc reference, see http://www.python.org/doc/essays/packages/

What If I Have a Module and a Package With The Same Name?

You may have a directory (on sys.path) which has both a module spam.py and a subdirectory spam that contains an _init_.py (without the _init_.py, a directory is not recognized as a package). In this case, the subdirectory has precedence, and importing spam will ignore the spam.py file, loading the package spam instead. If you want the module spam.py to have precedence, it must be placed in a directory that comes earlier in sys.path.

(Tip: the search order is determined by the list of suffixes returned by the function imp.get_suffixes(). Usually the suffixes are searched in the following order: ".so", "module.so", ".py", ".pyc". Directories don't explicitly occur in this list, but precede all entries in it.)

This doc doesn't explicitly mention ".pyd", but that's the Windows equivalent of ".so". I've just tested on a Windows machine, and indeed '.pyd' appears before '.py' in the suffix list.

Note that the reference given above is very old! Since this essay was written, the import system has been completely revamped, and the underlying machinery has been exposed for user access: you can mutate the sys.meta_path to register your own loaders or change precedence, for example. So it would be possible now to customize for '.py' to be preferred to '.pyd', and it doesn't matter much what imp.get_suffixes() has to say about anything (actually, that function is deprecated now). A default Python installation would not do that, of course, and the default precedence remains the same as the reference above has mentioned.

这篇关于“导入"是什么意思更喜欢 - .pyd (.so) 还是 .py?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆