【问题标题】:Is the import order of extensions in module filenames guaranteed in Python?Python 中是否保证了模块文件名中扩展名的导入顺序?
【发布时间】:2019-05-06 12:06:56
【问题描述】:

通过实验,我验证了当编译的extension.pyd(或.so)和普通的extension.py都存在于同一个目录中时,.pyd文件首先被导入;仅当找不到 .pyd 文件时才导入 .py

In [1]: import extension

In [2]: extension.__file__
Out[2]: 'extension.pyd'

In [3]: import glob; glob.glob("extension.py*")
Out[3]: ['extension.py', 'extension.pyd']

这是否保证对于所有版本的 Python 都是相同的,我是否可以依靠它向 .py 文件添加逻辑,该逻辑仅在找不到 .pyd 文件时执行?

【问题讨论】:

    标签: python python-import python-extensions


    【解决方案1】:

    FWIW,我找不到参考说明,扩展必须在 py 文件之前加载,因此将其视为实现细节可能更安全(除非有人提供参考)。即使这个细节对于所有版本都是稳定的,至少回到 2.7。

    当一个模块被导入时,它首先在缓存中查找(即sys.modules),如果还没有,则使用来自sys.meta_path的查找器。通常,sys.meta_pathBuiltinImporterFrozenImporterPathFinder 组成,其中PathFinder 负责查找磁盘/python-path 上的模块。

    PathFinder 提供了一些缓存功能来加快查找速度,但它基本上是从sys.path_hooksdelegates the searchhooks - 可以在例如PEP 302 中找到概述。

    通常,sys.path_hookszipimporter 组成,这使得导入压缩文件成为可能,and 一个包装好的 FileFinder,它是整个导入机器的工作马。

    FileFinder_get_supported_file_loaders()-method 建立的给定顺序尝试不同的后缀(即.so.py.pyc):

    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]
    

    如你所见:

    • 扩展位于源文件(即 py 文件)之前
    • 源文件在 pyc 文件之前

    显然,sys.meta_pathsys.path_hooks 可以通过某种方式进行操作,从而建立任意顺序的加载首选项。

    作为个人说明:我会尽量避免 py 和 so/pyd 文件彼此相邻的情况。

    【讨论】:

    • 谢谢,这是一个经过充分研究的答案!在标准中没有明确定义的行为的情况下,我基本上默认了相同的想法(避免这种情况)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-20
    • 1970-01-01
    • 2013-05-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多