本文介绍了Python中是否可以保证模块文件名中扩展名的导入顺序?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Experimentally, I verified that when a compiled extension.pyd (or .so) and plain extension.py both exist in the same directory, the .pyd file gets imported first ; the .py is only imported if the .pyd file is not found:

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文件添加逻辑吗?

Is that guaranteed to be the same for all versions of Python, and can I rely on this to add logic to the .py file that is only executed when the .pyd file is not found?

推荐答案

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

FWIW, I was not able to find a reference stating, that extensions must be loaded before py-files, thus it is probably safer to treat it as an implementation detail (unless somebody provides a reference). Even if this details is stable for all versions at least back to 2.7.

导入模块时,它首先在缓存中查找(即 sys.modules ),如果尚未找到,则来自 sys.meta_path .通常,sys.meta_pathBuiltinImporterFrozenImporter PathFinder ,其中PathFinder负责在磁盘/python-path上查找模块.

When a module is imported, it first looked-up in the cache (i.e. 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, where PathFinder is responsible for finding the modules on disk/python-path.

PathFinder提供了一些缓存功能以加快查找速度,但基本上将搜索委托钩子来自 -例如,可以在 PEP 302 .

PathFinder provides some caching functionality to speed-up the look-up, but it basically delegates the search to hooks from sys.path_hooks - an overview can be found for example in PEP 302.

通常,sys.path_hookszipimporter组成,这使得可以导入压缩文件,包装好的 FileFinder ,它是整个进口机器的主力.

Usually, sys.path_hooks consist of zipimporter, which make the import of zipped files possible, and a wrapped FileFinder, which is the working horse of the whole import-machinery.

FileFinder按给定顺序尝试不同的满足条件(即.so.py.pyc),该顺序由 _get_supported_file_loaders()-方法:

FileFinder tries out different suffices (i.e. .so, .py, .pyc) in a given order, which is established by _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]

可以看到:

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

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

Obviously, sys.meta_path as well as sys.path_hooks can be manipulated in a way, which establish an arbitrary order of load-preferences.

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

As personal note: I would try to avoid the situation where py- and so/pyd-files are next to eachother.

这篇关于Python中是否可以保证模块文件名中扩展名的导入顺序?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-20 13:21