Приоритет импорта Python: пакеты или модули? - PullRequest
11 голосов
/ 04 ноября 2010

Мне неясно, как правильно назвать этот вопрос.

Случай 1

Предположим, у меня есть следующая структура каталогов.

Если у меня есть

from foo import bar

Как узнать, какая полоса (bar.py или bar/__init__.py) импортируется?Есть ли простой способ автоматически обнаружить это?

Случай 2

foo
|
+- foo.py
|
+- other.py

Если other.py содержит строку

import foo

Как узнать, какой foo (foo или foo.foo) импортируется?Опять же, есть ли простой способ автоматически обнаружить это?

Ответы [ 4 ]

7 голосов
/ 04 ноября 2010

TLDR; пакет имеет приоритет над модулем с тем же именем, если он находится в одном каталоге.

Из документов:

"Когда импортируется модуль с именем spam, интерпретатор ищет файл с именем spam.py в текущем каталоге, а затем в списке каталогов, заданных переменной среды PYTHONPATH. Он имеет такой же синтаксис в качестве переменной оболочки PATH, то есть списка имен каталогов. "

Это немного вводит в заблуждение, потому что интерпретатор также будет искать пакет с именем spam (каталог с именем spam, содержащий файл __init__.py). Поскольку записи каталога сортируются перед поиском, пакеты имеют приоритет над модулями с одинаковыми именами, если они находятся в одном каталоге, поскольку spam предшествует spam.py.

Обратите внимание, что "текущий каталог" относится к основному пути сценария (тот, где __name__ == '__main__' is True). Так что, если вы набираете /home/billg и звоните /foo/bar.py, «текущий каталог» относится к /foo.

6 голосов
/ 04 ноября 2010

из оболочки питона:

from foo import bar

print bar.__file__

должен сказать вам, какой файл был импортирован

Rob

2 голосов
/ 04 ноября 2010

Пакеты (каталоги с __init__.py) имеют приоритет над модулями. Документацию по этому факту трудно найти, но вы можете увидеть это в источнике: python 2.7 , python 3.6 (спасибо @qff за поиск).

Вам также понадобится __init__.py в каталоге foo, чтобы ваш пример работал.

Если other.py находится внутри foo/, он загрузит foo.py (не каталог foo/), потому что сначала он будет искать в текущем каталоге (если вы не играли с PYTHONPATH или sys.path) .

0 голосов
/ 04 ноября 2010

в первом случае вы пытаетесь импортировать функциональную панель из файла 'foo.py'

Во втором вы пытаетесь импортировать файл 'foo.py'

...