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_path
和 sys.path_hooks
可以通过某种方式进行操作,从而建立 load-preferences.
的任意顺序
作为个人注意事项:我会尽量避免 py- 和 so/pyd-files 彼此相邻的情况。
根据实验,我验证了当编译的 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_path
和 sys.path_hooks
可以通过某种方式进行操作,从而建立 load-preferences.
作为个人注意事项:我会尽量避免 py- 和 so/pyd-files 彼此相邻的情况。