Абсолютный или явный относительный импорт модуля Python - PullRequest
72 голосов
/ 18 ноября 2010

Я задаюсь вопросом о предпочтительном способе импорта пакетов в приложении Python.У меня есть структура пакета, подобная этой:

project.app1.models
project.app1.views
project.app2.models

project.app1.views import project.app1.models и project.app2.models.Есть два способа сделать это:

С абсолютным импортом:

import A.A
import A.B.B

или с явным относительным импортом, как представлено в Python 2.5 с PEP 328 :

# explicit relative
import ..A
import .B

Какой самый питонский способ сделать это?

Ответы [ 3 ]

110 голосов
/ 25 мая 2013

Относительный импорт Python больше не рекомендуется, но в этом случае настоятельно рекомендуется использовать absolute_import.

Пожалуйста, смотрите это обсуждение , ссылаясь на самого Гвидо:

"Разве это в основном не исторически? До нового синтаксиса относительного импорта были реализованы различные проблемы с относительным импортом. краткосрочным решением было рекомендовать не использовать их. Долгосрочный Решение заключалось в реализации однозначного синтаксиса. Теперь пришло время снять антирекоменду Конечно, не выходя за борт - Я все еще нахожу их приобретенным вкусом; но у них есть свое место. "

ОП правильно связывает PEP 328 , который говорит:

Было представлено несколько вариантов использования, наиболее важным из которых является возможность изменить структуру больших пакетов без необходимости редактировать подпакеты. Кроме того, модуль внутри пакета не может легко импортировать сам без относительного импорта.

Также см. Почти повторяющийся вопрос Когда или зачем использовать относительный импорт в Python

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

Чтобы вызвать новое поведение из PEP 328, используйте:

from __future__ import absolute_import

В этом случае неявный относительный импорт больше не будет возможен (например, import localfile больше не будет работать, только from . import localfile). Для чистого и перспективного поведения рекомендуется использовать absolute_import.

Важным предупреждением является то, что из-за PEP 338 и PEP 366 для относительного импорта требуется импортировать файл python как модуль - вы не можете выполнить файл file.py, который имеет относительный импорт или вы получите ValueError: Attempted relative import in non-package.

Это ограничение следует учитывать при оценке наилучшего подхода. Гвидо против запуска скриптов из модуля в любом случае:

Я -1 на этом и на любом другом предложенном тидлинге механизма __main__. Похоже, что единственный вариант использования - запуск сценариев, которые живут внутри каталога модуля, который я всегда рассматривал как антипаттерн. Чтобы заставить меня передумать, ты должен убедить меня, что это не так.

Исчерпывающие дискуссии по этому вопросу можно найти на SO; число рейнольдса Python 3 это довольно всеобъемлющий:

42 голосов
/ 18 ноября 2010

Абсолютный импорт.От PEP 8:

Относительный импорт для импорта внутри упаковки крайне не рекомендуется.Всегда используйте абсолютный путь к пакету для всех импортов.Даже сейчас, когда PEP 328 [7] полностью реализован в Python 2.5, его стиль явного относительного импорта активно не рекомендуется;Абсолютный импорт более переносим и обычно более читабелен.

Явный относительный импорт - приятная языковая особенность (я полагаю), но он не так явен, как абсолютный импорт.Более читаемая форма:

import A.A
import A.B.B

, особенно если вы импортируете несколько разных пространств имен.Если вы посмотрите на некоторые хорошо написанные проекты / учебные пособия, которые включают импорт из пакетов, они обычно следуют этому стилю.

Несколько дополнительных нажатий клавиш, которые вы сделаете более явными, сэкономят другим (и, возможно, вам) много временив будущем, когда они попытаются выяснить ваше пространство имен (особенно если вы перейдете на 3.x, в котором некоторые имена пакетов изменились).

30 голосов
/ 18 ноября 2010

Относительный импорт не только дает вам свободу переименовывать ваш пакет позже, не изменяя десятки внутренних импортов, но я также имел успех с ними в решении определенных проблем, связанных с такими вещами, как циклический импорт или пакеты пространства имен, потому что они не отправляют Python "вернуться к началу », чтобы снова начать поиск следующего модуля из пространства имен верхнего уровня.

...