2010-11-03 5 views
10

Мне было непонятно, как правильно назвать этот вопрос.Python приоритет импорта: пакеты или модули?

Случай 1

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

foo 
| 
+- bar/__init__.py 
| 
+- bar.py 

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

from foo import bar 

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

Случай 2

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

Если other.py имеет линию

import foo 

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

+2

Легкого способом обнаружить: есть первая линия bar.py будет 'печати (" бар .py импортировано ")' – nmichaels

+2

У меня должен быть RTFM-редактор. http://docs.python.org/tutorial/modules.html - отличный ресурс. –

+0

Есть ли способ заставить программу использовать одну интерпретацию или другую? – Sobi

ответ

6

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

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

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

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

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

+1

У вас все изменилось? потому что я, кажется, не получаю текущий каталог, добавленный, как вы предлагаете. Теперь в документах указано: «Когда импортируется модуль с именем spam, интерпретатор сначала ищет встроенный модуль с этим именем. Если он не найден, он затем ищет файл с именем spam.py в списке каталогов, заданных переменная sys.path ". И я не вижу, что указан «текущий каталог». Но поскольку я потерялся, возможно, я не понимаю? – PatrickT

+1

И (я мог бы не понимать все это) предыдущий ответ на stackoverflow указывает: «Python не добавляет текущий каталог в sys.path, а скорее каталог, в котором находится скрипт». http://stackoverflow.com/questions/2325923/how-to-fix-importerror-no-module-named-error-in-python – PatrickT

+0

Это, похоже, не отвечает ** Случай 1 ** – qff

0

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

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

2

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

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

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

+0

Как вы знаете, что это имеет приоритет? - Я не смог найти его в [документации Python] (https://docs.python.org/2/tutorial/modules.html) – qff

+0

@qff Я протестировал его. Я также тестировал python3 только сейчас, и он имеет такое же поведение. Ссылка на официальную документацию на этот факт была бы хорошей. Если вы его найдете, не стесняйтесь отредактировать мой ответ или оставить комментарий, и я его отредактирую. – kanaka

+0

Нашел! (вид) - записи каталога сортируются, прежде чем пытаться загрузить их как пакет или модуль. Это гарантирует, что пакеты будут загружены первыми. [Ссылка на исходный код CPython] (https://github.com/python/cpython/blob/c30098c8c6014f3340a369a31df9c74bdbacc269/Lib/pkgutil.py#L235) – qff

5

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

from foo import bar 

print bar.__file__ 

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

Роб

+0

не имеет атрибут __file__ на python3 – gabn88

Смежные вопросы