Modul importiert und __init__.py in Python
Ich versuche zu verstehen, was die best practices sind mit Bezug auf Python (v2.7) import-mechanik. Ich habe ein Projekt, das begonnen hat zu wachsen ein wenig und können sagen, mein code ist folgendermaßen organisiert:
foo/
__init__.py
Foo.py
module1.py
module2.py
module3.py
Den Namen des Pakets ist foo
- und unterhalb habe ich Modul Foo.py
enthält code für die Klasse Foo
. Also ich bin mit dem gleichen Namen für das Paket, Modul und Klasse, die vielleicht nicht sehr clever, mit zu beginnen.
__init__.py
leer ist und Klasse Foo
muss importieren module1, module2 and module3
daher Teil meiner Foo.py
- Datei sieht wie folgt aus:
# foo/Foo.py
import module1
import module2
import module3
class Foo(object):
def __init__(self):
....
....
if __name__ == '__main__':
foo_obj = Foo()
Allerdings habe ich später nachgeholt, und ich dachte, es würde besser sein, dass alle Importe in die __init__.py
- Datei. Daher meine __init__.py
jetzt aussieht:
# foo/__init__.py
import Foo
import module1
import module2
import module3
....
....
und meine Foo.py
muss nur importieren foo
:
# foo/Foo.py
import foo
Während dies sieht übersichtlich aus, da es ein one-liner, ich bin ein bisschen besorgt, dass es vielleicht schaffen zirkuläre Importe. Was ich meine ist, dass wenn das Skript Foo.py
ausgeführt wird importieren, alles, was es kann und dann __init__.py
genannt werden, die importiert Foo.py
wieder (ist das richtig?). Zusätzlich mit den gleichen Namen für das Paket, Modul und Klasse macht die Dinge eher verwirrend.
Macht es Sinn, die Art, wie ich es getan haben? Oder bin ich da ärger?
Du musst angemeldet sein, um einen Kommentar abzugeben.
Ein paar Dinge, die Sie tun können, um zu verbessern Ihre organizaton, wenn nur zu halten, um einige beliebte python-Konventionen und Normen.
Wenn Sie suchen, in diesem Thema, werden Sie unweigerlich stoßen Menschen empfehlen die PEP8 Richtlinien. Diese sind de facto die kanonischen Normen für die Organisation von python-code.
Basierend auf diesen Richtlinien, Projekt-Module sollten wie folgt benannt:
Ich finde es im Allgemeinen am besten zu vermeiden, Module zu importieren, unnötig in
__init__.py
es sei denn, du tust es für namespace Gründen. Zum Beispiel, wenn Sie möchten, dass der namespace für Ihr Paket zu suchen, wie diesestatt
Dann ist es sinnvoll,
in Ihrem
__init__.py
. Als Ihr Paket größer wird, möglicherweise einige Benutzer nicht verwenden möchten, werden alle sub-Pakete und-Module, so ist es nicht sinnvoll zu erzwingen, dass der Benutzer warten, bis alle Module geladen werden, indem implizit importieren Sie Sie in Ihrem__init__.py
. Außerdem müssen Sie entscheiden, ob Sie das auch wollenmodule1
,module2
, undmodule3
als Teil der externen API. Sind Sie nur vonFoo
und nicht gedacht für Endbenutzer? Wenn Sie nur intern benutzt werden, dann nicht in die__init__.py
Ich würde auch empfehlen die Verwendung von absolute oder explizite relative Importe für den Import von sub-Modulen. Zum Beispiel, in
foo.py
Absolute
Explizite Relative
Damit verhindern Sie jede mögliche Benennung von Problemen mit anderen Paketen und Modulen. Es wird auch machen es einfacher, wenn Sie sich entscheiden, zu unterstützen Python ist3, da der implizite relative import-syntax, die Sie derzeit verwenden, ist nicht unterstützt in Python ist3.
Außerdem, Sie können Dateien in Ihr Paket in der Regel sollte nicht enthalten eine
Dies ist, weil Sie eine Datei als Skript bedeutet, es wird nicht als Teil des Pakets, zu dem er gehört, damit er nicht in der Lage sein, um die relative Importe.
Der beste Weg, um ausführbare Skripte für Benutzer mithilfe der
- Skripts
oderconsole_scripts
- Funktion dessetuptools
. Die Art und Weise organisieren Sie Ihre Skripte können unterschiedlich sein, je nachdem, welche Methode Sie verwenden, aber ich in der Regel organisieren mine, wie dieser:import module1
).Laut PEP 0008, "Öffentliche und interne Schnittstellen":
So würde dies vorschlagen, dass es ist ok zu setzen, die Importe in die
__init__
- Modul, wenn__init__
verwendet wird, um die expose-Funktionen aus Submodule. Hier ist einen kurzen blog-post fand ich mit ein paar Beispielen von Pythonic verwendet__init__
mit Importen zu machen Unterpakete, zur Verfügung auf der Paketebene.Ihrem Beispiel bewegen Sie die import-Anweisungen
__init__
um nur ein import inFoo
tut nicht scheinen diese Regel befolgen. Meine interpretation ist, dass die Einfuhr in Ihrem__init__
sollte verwendet werden, für externe Schnittstellen, ansonsten legen Sie einfach Ihre import-Anweisungen in der Datei, die Sie braucht. Dies erspart Ihnen die Mühe, wenn Submodul Namen ändern, und hält Sie von unnötigen oder schwer-zu-finden-Importe, wenn Sie weitere Dateien hinzuzufügen, dass die Verwendung einer anderen Untermenge der teilmodule.Soweit Zirkelbezüge, das ist definitiv möglich, in Python (zum Beispiel). Ich schrieb das, bevor ich tatsächlich versucht, Ihr Spielzeug Beispiel, aber um das Beispiel der Arbeit hatte ich, um
Foo.py
eine Ebene nach oben, etwa so:Mit diesem setup und einige print-Anweisungen ausgeführt
python Foo.py
gibt die Ausgabe:und wird normalerweise beendet. Beachten Sie, dass dies durch hinzufügen der
if __name__ == "__main__"
- wenn Sie fügen Sie eine print-Anweisung außerhalb der, dass, können Sie sehen, Python ist noch geladen werden, das Modul zweimal. Eine bessere Lösung wäre das entfernen der import von__init__.py
. Wie ich bereits sagte,, die möglicherweise oder möglicherweise nicht sinnvoll, je nachdem, was diese Submodule werden.__all__
funktioniert (die hat Ihre eigenen Stil-Probleme ... aber das ist ein anderes Thema). Unabhängig davon, hast du sicher Recht, dass wildcard-Importe sind nicht von gutem Stil!Finden Sie in der "Style Guide for Python Code" für die besten Praktiken, die zu importieren ist, bleibt in der Klasse in dieser Anleitung.
https://www.python.org/dev/peps/pep-0008/#imports
Versuchen Sie dies:
package1
package2
package1.py:-
init.VJ:-
package2.py:-
Ich diese verwenden __init__.py importieren aus einem Paket.
Ich kann kein Staat definitiv ist dies der richtige Weg ist, aber ich habe es immer getan, die den ehemaligen Weg. Das heißt, ich habe immer
__init__.py
leer, und nur die importierten Sachen innerhalbFoo.py
als nötig.Aus wie du es beschreibst, scheint es wie es ist eine zirkuläre Logik geschieht in der letzteren form.