Python 中是否保证模块文件名中扩展名的导入顺序?

Is the import order of extensions in module filenames guaranteed in Python?

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

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 都相同,我可以依靠它向仅在 .pyd 时执行的 .py 文件添加逻辑吗找不到文件?

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

导入模块时,它首先looked-up在缓存中(即sys.modules) and if not yet there, the finders from sys.meta_path are used. Usually, sys.meta_path consist of BuiltinImporter, FrozenImporter and PathFinder,其中PathFinder负责查找disk/python-path上的模块。

PathFinder 为 speed-up 和 look-up 提供了一些缓存功能,但它基本上是 delegates the search to hooks from sys.path_hooks - an overview can be found for example in PEP 302.

通常,sys.path_hooks 包括 zipimporter,这使得压缩文件的导入成为可能,and a wrapped FileFinder,这是整个 import-machinery 的工作马。

FileFinder 按照给定的顺序尝试不同的后缀(即 .so.py.pyc),该顺序由 _get_supported_file_loaders()-method 建立:

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]

如你所见:

  • 扩展名在 source-files 之前(即 py-files)
  • source-files 排在 pyc-files
  • 之前

显然,sys.meta_pathsys.path_hooks 可以通过某种方式进行操作,从而建立 load-preferences.

的任意顺序

作为个人注意事项:我会尽量避免 py- 和 so/pyd-files 彼此相邻的情况。