Зміни в заяві імпорту 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 це більше не дозволено, і ви можете робити імпорт зірок лише на верхньому рівні модуля (не всередині функцій чи класів).


6
Чому було прийнято таке рішення?
Дор

1
Я здогадуюсь, що ідея, що стоїть за ним, - "Явне краще, ніж неявне". від PEP20 - Дзен Пітона. Точка перед модулем робить відносне / відносне посилання явним, таким чином, вирішуючи можливі колізії імен. Хоча "Читання рахується". страждає незначно.
Pafnucy

2
Ні, насправді це було "протилежне", "практичність перемагає чистоту". Це було необхідно для оптимізації доступу до змінних до внутрішніх функцій, оскільки без "імпорту *" компілятор завжди знає, аналізуючи код, які змінні є локальними і їх можна шукати безпосередньо. Насправді функції навіть не використовують 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
Rodrigo E. Principe

@ RodrigoE.Principe і так здається import ..uncle. Виправлено. О, що я думав ... напевно, відволіклися лицарі, які кажуть Ні!
Акселі Пален

4

До відповіді Міхала Горного додав ще один випадок:

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.