Изменения в операторе импорта python3

177

Я не понимаю следующее из pep-0404

В Python 3 неявный относительный импорт внутри пакетов больше недоступен - поддерживаются только абсолютный и явный относительный импорт. Кроме того, импорт звездочек (например, из x import *) разрешен только в коде уровня модуля.

Что такое относительный импорт? В каких других местах импорт звезд разрешен в python2? Пожалуйста, объясните с примерами.

Балки
источник

Ответы:

277

Относительный импорт происходит всякий раз, когда вы импортируете пакет относительно текущего скрипта / пакета.

Рассмотрим, например, следующее дерево:

mypkg
├── base.py
└── derived.py

Теперь ваш derived.pyтребует чего-то от base.py. В Python 2 вы можете сделать это следующим образом (в derived.py):

from base import BaseThing

Python 3 больше не поддерживает это, поскольку неясно, хотите ли вы «относительный» или «абсолютный» base. Другими словами, если baseв системе установлен пакет Python с именем , вы получите неправильный.

Вместо этого он требует использования явных импортов, которые явно указывают местоположение модуля на основе пути. Ваш derived.pyбудет выглядеть так:

from .base import BaseThing

Ведущий .говорит «импорт baseиз каталога модулей»; другими словами, .baseкарты для ./base.py.

Точно так же есть ..префикс, который идет вверх по иерархии каталогов, например ../..modотображением на ../mod.py), а затем ...идет на два уровня вверх ( ../../mod.py) и так далее.

Однако обратите внимание, что перечисленные выше относительные пути относились к каталогу, в котором находится текущий модуль ( derived.py), а не к текущему рабочему каталогу.


@BrenBarn уже объяснил случай импорта звезд. Для полноты мне придется сказать то же самое;).

Например, вам нужно использовать несколько mathфункций, но вы используете их только в одной функции. В Python 2 вам было позволено быть ленивым:

def sin_degrees(x):
    from math import *
    return sin(degrees(x))

Обратите внимание, что это уже вызывает предупреждение в Python 2:

a.py:1: SyntaxWarning: import * only allowed at module level
  def sin_degrees(x):

В современном коде Python 2 вы должны, а в Python 3 вы должны сделать либо:

def sin_degrees(x):
    from math import sin, degrees
    return sin(degrees(x))

или:

from math import *

def sin_degrees(x):
    return sin(degrees(x))
Михал Гурны
источник
14

Относительно импорта см. Документацию . Относительный импорт - это когда вы импортируете из модуля относительно его местоположения, а не из абсолютно sys.path.

Что касается import *Python 2, то разрешен импорт звезд внутри функций, например:

>>> def f():
...     from math import *
...     print sqrt

Предупреждение об этом выдается в Python 2 (по крайней мере, в последних версиях). В Python 3 это больше не разрешено, и вы можете выполнять импорт звездочек только на верхнем уровне модуля (не внутри функций или классов).

BrenBarn
источник
6
Почему было принято это решение?
Дор
1
Я думаю, что идея заключается в том, что «явное лучше, чем неявное». из PEP20 - Дзен Питона. Точка перед модулем делает относительное / нерелятивное связывание явным, что устраняет возможные конфликты имен. Хотя «Читаемость имеет значение». немного страдает.
Пафнуци
2
Нет, на самом деле это было «противоположное» решение «практичность побеждает чистоту». Это было необходимо для оптимизации доступа к локальным переменным внутри функций, поскольку без «import *» компилятор всегда просто анализирует код, какие переменные являются локальными и могут быть найдены напрямую. Фактически, функции даже не используют dict для локального хранения, а оптимизированный массив, где переменные получают уникальные индексы.
Век
11

Для поддержки Python 2 и Python 3 используйте явный относительный импорт, как показано ниже. Они относительно текущего модуля. Они поддерживаются начиная с 2.5 .

from .sister import foo
from . import brother
from ..aunt import bar
from .. import uncle
Аксели Пален
источник
14
import .brother выдает мне неверную синтаксическую ошибку в Python 3.5. Это нормально? У меня есть init .py в каталоге, в котором он находится
Frikster
1
import .brotherневерный синтаксис для Python 2 и 3
Родриго Э. Принсипи
@ RodrigoE.Principe и так вроде бы import ..uncle. Исправлена. О чем я думал ... вероятно, отвлекся на рыцарей, которые говорят Ni!
Аксели Пален
4

В ответ Михаила Гурни добавлен еще один случай:

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

Панфэн Ли
источник