Zmiany w instrukcji importu python3

177

Nie rozumiem następujących z pep-0404

W Pythonie 3 niejawne importy względne w pakietach nie są już dostępne - obsługiwane są tylko import bezwzględny i jawny import względny. Ponadto import gwiazdek (np. Z importu x *) jest dozwolony tylko w kodzie na poziomie modułu.

Co to jest import względny? W jakich innych miejscach import gwiazdy był dozwolony w python2? Proszę wyjaśnić przykładami.

balki
źródło

Odpowiedzi:

277

Względny import ma miejsce za każdym razem, gdy importujesz pakiet względem bieżącego skryptu / pakietu.

Rozważmy na przykład następujące drzewo:

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

Teraz derived.pypotrzebujesz czegoś od base.py. W Pythonie 2 można to zrobić w następujący sposób (w derived.py):

from base import BaseThing

Python 3 już tego nie obsługuje, ponieważ nie jest jasne, czy chcesz mieć wartość „względną” czy „absolutną” base. Innymi słowy, jeśli basew systemie był zainstalowany pakiet Pythona o nazwie , otrzymasz niewłaściwy.

Zamiast tego wymaga użycia jawnych importów, które jawnie określają lokalizację modułu na podstawie podobnych ścieżek. Twój derived.pywyglądałby tak:

from .base import BaseThing

Wiodący .mówi „import basez katalogu modułów”; innymi słowy, .basemapuje do ./base.py.

Podobnie, istnieje ..prefiks, który przechodzi w górę w hierarchii katalogów, jak ../(z ..modmapowaniem do ../mod.py), a następnie ...przechodzi o dwa poziomy w górę ( ../../mod.py) i tak dalej.

Należy jednak pamiętać, że ścieżki względne wymienione powyżej odnosiły się do katalogu, w którym znajduje się bieżący moduł ( derived.py), a nie do bieżącego katalogu roboczego.


@BrenBarn wyjaśnił już przypadek importu gwiazdy. Dla kompletności powiem to samo;).

Na przykład musisz użyć kilku mathfunkcji, ale używasz ich tylko w jednej funkcji. W Pythonie 2 pozwolono ci być częściowo leniwym:

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

Zauważ, że już wyzwala ostrzeżenie w Pythonie 2:

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

We współczesnym kodzie Python 2 powinieneś, aw Pythonie 3 musisz zrobić albo:

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

lub:

from math import *

def sin_degrees(x):
    return sin(degrees(x))
Michał Górny
źródło
14

W przypadku przywozu względnych zobaczyć dokumentację . Względny import ma miejsce, gdy importujesz z modułu względem lokalizacji tego modułu, a nie absolutnie z sys.path.

Jeśli chodzi o import *Python 2, zezwalał na importowanie gwiazd w funkcjach, na przykład:

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

W tym przypadku w Pythonie 2 (przynajmniej w najnowszych wersjach) pojawia się ostrzeżenie. W Pythonie 3 nie jest to już dozwolone i możesz dokonywać importu gwiazdek tylko na najwyższym poziomie modułu (nie w funkcjach lub klasach).

BrenBarn
źródło
6
Dlaczego podjęto taką decyzję?
Dor
1
Domyślam się, że idea, która się za tym kryje, brzmi: „Wyraźne jest lepsze niż ukryte”. z PEP20 - Zen Pythona. Kropka przed modułem sprawia, że ​​relatywne / nierelatywne linkowanie jest jawne, rozwiązując tym samym możliwe kolizje nazw. Chociaż „liczy się czytelność”. lekko cierpi.
Pafnucy
2
Nie, w rzeczywistości była to decyzja „odwrotna”, „praktyczność jest ważniejsza od czystości”. Było to konieczne, aby zoptymalizować dostęp do zmiennych lokalnych w funkcjach, ponieważ bez "importu *" kompilator zawsze wie tylko analizując kod, jakie zmienne są lokalne i można je bezpośrednio wyszukać. W rzeczywistości funkcje nie używają nawet dyktowania do lokalnej pamięci, ale zoptymalizowaną tablicę, w której zmienne otrzymują unikalne indeksy.
Veky
11

Aby obsługiwać zarówno Python 2, jak i Python 3, użyj jawnych importów względnych, jak poniżej. Odnoszą się do bieżącego modułu. Są obsługiwane począwszy od 2.5 .

from .sister import foo
from . import brother
from ..aunt import bar
from .. import uncle
Akseli Palén
źródło
14
import .brother daje mi nieprawidłowy błąd składni w Pythonie 3.5. To normalne? Mam init .py w katalogu, w którym się znajduje
Frikster
1
import .brotherma niepoprawną składnię zarówno dla Pythona 2, jak i 3
Rodrigo E. Principe
@ RodrigoE.Principe i wydaje się, że tak jest import ..uncle. Naprawiony. Och, co ja sobie myślałem ... prawdopodobnie rozproszyli mnie rycerze, którzy mówią Ni!
Akseli Palén
4

Do odpowiedzi Michała Górnego dodano kolejny przypadek:

Zwróć uwagę, że import względny jest oparty na nazwie bieżącego modułu. Ponieważ nazwa modułu głównego to zawsze " __main__", moduły przeznaczone do użycia jako moduł główny aplikacji Python muszą zawsze używać importu bezwzględnego.

Panfeng Li
źródło