Absoluter vs. expliziter relativer Import des Python-Moduls

84

Ich frage mich, wie Pakete in eine Python-Anwendung bevorzugt importiert werden können. Ich habe eine Paketstruktur wie diese:

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

project.app1.viewsImporte project.app1.modelsund project.app2.models. Es gibt zwei Möglichkeiten, dies zu tun, die mir in den Sinn kommen.

Mit absoluten Importen:

import A.A
import A.B.B

oder mit expliziten relativen Importen, wie in Python 2.5 mit PEP 328 eingeführt :

# explicit relative
from .. import A
from . import B

Was ist der pythonischste Weg, dies zu tun?

Daniel Hepper
quelle
Die "expliziten relativen" Beispiele sind Syntaxfehler. Relative Importe müssen in der Form sein from _ import ..., also wären Ihre Beispiele from .. import Aundfrom . import B
MestreLion
@MestreLion Guter Fang, du hast absolut Recht! Ich habe meine Frage von import ..Aauf aktualisiert from .. import A. Bemerkenswert, dass es nur 9 Jahre dauerte, bis es jemand bemerkte;)
Daniel Hepper

Antworten:

52

Absolute Importe. Aus PEP 8:

Von relativen Importen für Intra-Package-Importe wird dringend abgeraten. Verwenden Sie für alle Importe immer den absoluten Paketpfad. Selbst jetzt, da PEP 328 [7] vollständig in Python 2.5 implementiert ist, wird von seiner Art expliziter relativer Importe aktiv abgeraten. Absolute Importe sind portabler und normalerweise besser lesbar.

Explizite relative Importe sind eine nette Sprachfunktion (denke ich), aber sie sind bei weitem nicht so explizit wie absolute Importe. Die besser lesbare Form ist:

import A.A
import A.B.B

vor allem, wenn Sie mehrere verschiedene Namespaces importieren. Wenn Sie sich einige gut geschriebene Projekte / Tutorials ansehen, die Importe aus Paketen enthalten, folgen sie normalerweise diesem Stil.

Die wenigen zusätzlichen Tastenanschläge, die Sie verwenden, um expliziter zu werden, sparen anderen (und möglicherweise Ihnen) in Zukunft viel Zeit, wenn sie versuchen, Ihren Namespace herauszufinden (insbesondere, wenn Sie auf 3.x migrieren, in dem ein Teil des Pakets enthalten ist) Namen haben sich geändert).

Rafe Kettler
quelle
@Rafe, "schau dir einige gut geschriebene Projekte an ..." irgendwelche Vorschläge?
Denis
@Denis: Rietveld ist Guido van Rossums eigenes Projekt, daher würde ich mir vorstellen, dass dies ein guter Ort ist, um nachzuschauen ( code.google.com/p/rietveld ). Die Python-Standardbibliothek ist nicht so toll, ein Großteil dieses Codes folgt nicht den Konventionen.
Rafe Kettler
66
@Rafe: Dieser Teil von PEP-8 ist laut Guido veraltet. mail.python.org/pipermail/python-dev/2010-October/104476.html
Brandon Rhodes
12
Diese Aussage ist jetzt überhaupt nicht mehr in PEP-8 enthalten. Es heißt nun, dass absolute Importe empfohlen werden, relative Importe jedoch eine akzeptable Alternative sind.
Dano
6
Das Problem, das ich bei absoluten Importen habe, ist die Verwendung eines Pakets in einem anderen Paket. In meinem Fall ist es als Git-Submodul vorhanden. In diesem Fall können, obwohl ich das Paket der obersten Ebene importieren kann, keine Pakete darunter importiert werden, da sie keine eigenen Module mit absoluten Importen finden. Wenn ich auf dieser untersten Ebene relative Importe verwende, funktioniert alles einfach.
Davida
122

Von relativen Python-Importen wird nicht mehr dringend abgeraten. In diesem Fall wird jedoch die Verwendung von absolute_import dringend empfohlen.

Bitte sehen Sie diese Diskussion unter Berufung auf Guido selbst:

"Ist das nicht größtenteils historisch? Bis zur Implementierung der neuen Relativimportsyntax gab es verschiedene Probleme mit Relativimporten. Die kurzfristige Lösung bestand darin, zu empfehlen, sie nicht zu verwenden. Die langfristige Lösung bestand darin, eine eindeutige Syntax zu implementieren. Jetzt Es ist Zeit, die Anti-Empfehlung zurückzuziehen. Natürlich, ohne über Bord zu gehen - ich finde sie immer noch einen erworbenen Geschmack; aber sie haben ihren Platz. "

Das OP verbindet den PEP 328 korrekt mit der Aufschrift :

Es wurden mehrere Anwendungsfälle vorgestellt, von denen der wichtigste darin besteht, die Struktur großer Pakete neu zu ordnen, ohne Unterpakete bearbeiten zu müssen. Darüber hinaus kann sich ein Modul in einem Paket ohne relative Importe nicht einfach selbst importieren.

Siehe auch fast doppelte Frage Wann oder warum relative Importe in Python verwendet werden sollen

Natürlich ist es immer noch Geschmackssache. Es ist zwar einfacher, Code mit relativen Importen zu verschieben, dies kann jedoch auch zu unerwarteten Problemen führen. und das Umbenennen der Importe ist nicht so schwierig.

Um das neue Verhalten von PEP 328 zu erzwingen, verwenden Sie:

from __future__ import absolute_import

In diesem Fall ist ein impliziter relativer Import nicht mehr möglich (z. import localfile funktioniert er nicht mehr from . import localfile). Für ein sauberes und zukunftssicheres Verhalten ist die Verwendung von absolute_import ratsam.

Eine wichtige Einschränkung ist die wegen PEP 338 und PEP 366 für relative Importe die Python-Datei als Modul importiert werden muss. Sie können keine Datei.py ausführen, die einen relativen Import hat, oder Sie erhalten eine ValueError: Attempted relative import in non-package.

Diese Einschränkung sollte bei der Bewertung des besten Ansatzes berücksichtigt werden. Guido ist auf jeden Fall gegen das Ausführen von Skripten aus einem Modul:

Ich bin -1 in diesem und in jedem anderen vorgeschlagenen Twiddling der __main__ -Maschinerie. Der einzige Anwendungsfall scheint darin zu bestehen, Skripte auszuführen, die sich zufällig im Verzeichnis eines Moduls befinden, das ich immer als Antimuster gesehen habe. Um mich dazu zu bringen, meine Meinung zu ändern, müsstest du mich davon überzeugen, dass es nicht so ist.

Ausführliche Diskussionen zu diesem Thema finden Sie auf SO; Re. Python 3 ist dies ziemlich umfassend:

Stefano
quelle
9
Guido hat das 2010 geschrieben und es ist immer noch in der PEP? Wie können wir PEPs vertrauen, wenn sie so veraltet sind?
Jabba
2
PEP sind wie US-Änderungsanträge in dem Sinne, dass Sie Dinge ändern können. Es gibt auch viele abgelehnte PEPS. PEPs sind Vorschläge. Sie können akzeptiert, abgelehnt oder veraltet sein, was häufig neue PEP bedeutet. PEP 8 ist ein Styleguide, der an Ort und Stelle geändert werden kann.
CppLearner
2
Ich bin verwirrt über den Teil "Ein Modul in einem Paket kann sich nicht einfach selbst importieren ...". Ich hatte noch nie von Modulen gehört, die sich selbst importieren.
Matiascelasco
2
Ein mögliches Beispiel @matiascelasco: Wenn Sie foo / bar.py und foo / baz.py haben, aber auch baz.py woanders. Wenn Sie foo.baz aus der Leiste importieren möchten, möchten Sie möglicherweise sicher sein, was Sie importieren, z. import .baz- Dies ist jedoch nur eine Vereinfachung vieler ähnlicher Situationen, die im PEP beschrieben sind.
Stefano
Ihre Antwort unterscheidet nicht klar die Änderung, wenn Sie sie zulassen. Implizite relative Importe sollten niemals verwendet werden, aber explizite relative Importe können verwendet werden. Der implizite Verwandte wurde aus Python3 entfernt.
NinMonkey
33

Relative Importe ermöglichen es Ihnen nicht nur, Ihr Paket später umzubenennen, ohne Dutzende interner Importe zu ändern, sondern ich habe auch Erfolg damit gehabt, bestimmte Probleme zu lösen, die z. B. zirkuläre Importe oder Namespace-Pakete betreffen, da sie Python nicht zurück an die senden top ", um die Suche nach dem nächsten Modul erneut über den Namespace der obersten Ebene zu starten.

Brandon Rhodes
quelle
4
Dies ist der entmutigte Stil gemäß dem Python-Styleguide. Sie trüben die Lesbarkeit erheblich und sind die wahrgenommene "Bequemlichkeit", auf die Sie anspielen, nicht wert. Wenn Sie relative Importe verwenden müssen, um ein Problem zu lösen, machen Sie es falsch.
Rafe Kettler
14
Beachten Sie seinen Kommentar (Brandon Rhodes) zu der anderen Antwort, wobei ein Link zeigt, dass davon nicht mehr abgeraten wird.
Jon Coombs
1
@RafeKettler Können Sie erklären, wie Sie absolute Importe in einem Paket verwenden würden, das selbst in einem anderen Paket enthalten ist? Die absoluten Importe schlagen innerhalb des inneren Pakets fehl, da sie nichts über die neue oberste Ebene wissen. Relative Importe funktionieren weiterhin. Man könnte wahrscheinlich argumentieren, dass das Paket überhaupt nicht in einem anderen verschachtelt werden sollte, aber ein Teil des Codes soll wiederverwendbar sein, und dies passiert häufig. Viele wiederverwendete Codes sind nicht für die Öffentlichkeit verpackt und werden daher nicht als separates Paket bereitgestellt, sodass stattdessen Ad-hoc-Methoden wie VCS-Import / Submodule verwendet werden
davidA
3
@meowsqueak Ich stimme zu, einige Pakete sind nicht einfach zu installieren (sie sind nicht auf Pip, Sie möchten sie nicht verwenden python setup.py installoder python setup.py developaus welchem ​​Grund auch immer). In diesen Fällen gable ich den Quellcode und füge ihn als Git-Submodul hinzu. Wenn diese Pakete absolute Importe für ihren eigenen Paketnamen verwenden, schlagen ihre Importe fehl. Die einzige Lösung besteht darin, explizite relative Importe zu verwenden. Das sollte meiner Meinung nach gefördert werden.
CMCDragonkai