В типичной установке Python класс ExtensionFileLoader
имеет приоритет над SourceFileLoader
, который используется для файлов .py
. Это ExtensionFileLoader
, который обрабатывает импорт .pyd
файлов, и на машине с Windows вы найдете .pyd
, зарегистрированный в importlib.machinery.EXTENSION_SUFFIXES
(примечание: в Linux / macOS он будет иметь .so
ввместо этого).
Таким образом, в случае конфликта имен в одном и том же каталоге (что означает «связь» при просмотре sys.path
по порядку), файл a.pyd
имеет приоритет над файлом a.py
,Вы можете убедиться, что при создании пустых файлов a.pyd
и a.py
оператор import a
пытается загрузить DLL (и, конечно, не удается).
Чтобы увидеть приоритет в исходниках CPython, посмотрите здесь в 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!
Ссылку на документ см. http://www.python.org/doc/essays/packages/
Что делать, если у меня есть модуль и пакетС тем же именем?
У вас может быть каталог (на sys.path), в котором есть как модуль spam.py, так и спам подкаталога, содержащий __init__.py (без __init__.py,каталог не распознается как пакет). В этом случае подкаталог имеет приоритет, и импорт спама будет игнорировать файл spam.py, загружая вместо этого спам пакета. Если вы хотите, чтобы модуль spam.py имел приоритет, он должен быть помещен в каталог, который находится ранее в sys.path.
(Совет: порядок поиска определяется списком суффиксов, возвращаемых функциейimp.get_suffixes (). Обычно суффиксы ищутся в следующем порядке: ".so", "module.so", ".py", ".pyc". Каталоги не появляются явно в этом списке, но предшествуют всемзаписей в нем.)
В этом документе явно не упоминается ".pyd", но это Windows-эквивалент ".so". Я только что проверил на компьютере с Windows, и действительно '.pyd'
появляется перед '.py'
в списке суффиксов.
Обратите внимание, что приведенная выше ссылка очень старая! Со времени написания этого эссе система импорта была полностью переработана, и основной механизм был открыт для пользователей (например, вы можете изменить sys.meta_path
, чтобы зарегистрировать свои собственные загрузчики или изменить приоритет). Так что теперь можно было бы настроить «.py» так, чтобы он был предпочтительнее «.pyd», и не имеет большого значения, что imp.get_suffixes()
говорит о чем-либо (на самом деле, эта функция устарела). Конечно, установка по умолчанию на Python этого не сделает, и приоритет по умолчанию останется таким же, как упомянуто выше.