Laut dem folgenden Kommentar von @Rob_before_edits und diesem Stackoverflow-Thread 37139786 wird init .py für Python 3.3+ anscheinend nicht mehr benötigt.
Python definiert zwei Arten von Paketen, reguläre Pakete und Namespace-Pakete. Normale Pakete sind traditionelle Pakete, wie sie in Python 3.2 und früheren Versionen vorhanden waren. Ein reguläres Paket wird normalerweise als Verzeichnis implementiert, das eine __init__.pyDatei enthält. Wenn ein reguläres Paket importiert wird, wird diese __init__.pyDatei implizit ausgeführt, und die von ihr definierten Objekte werden an Namen im Namespace des Pakets gebunden. Die __init__.pyDatei kann denselben Python-Code enthalten, den jedes andere Modul enthalten kann, und Python fügt dem Modul beim Import einige zusätzliche Attribute hinzu.
Klicken Sie einfach auf den Link. Er enthält ein Beispiel, weitere Informationen und eine Erläuterung der Namespace-Pakete, der Art von Paketen ohne __init__.py.
Was bedeutet dies: "Dies geschieht, um zu verhindern, dass Verzeichnisse mit einem allgemeinen Namen, wie z. B. eine Zeichenfolge, unbeabsichtigt gültige Module verbergen, die später im Modul-Suchpfad auftreten."
Carl G
97
@CarlG Python durchsucht eine Liste von Verzeichnissen , um Namen in z. B. Importanweisungen aufzulösen. Da es sich um ein beliebiges Verzeichnis handeln kann und vom Endbenutzer beliebige hinzugefügt werden können, müssen sich die Entwickler um Verzeichnisse kümmern, die zufällig einen Namen mit einem gültigen Python-Modul teilen, z. B. 'string' im Beispiel docs. Um dies zu vermeiden, werden Verzeichnisse ignoriert, die keine Datei mit dem Namen _ _ init _ _.py (keine Leerzeichen) enthalten, auch wenn sie leer ist.
Zwei-Bit-Alchemist
186
@CarlG Versuchen Sie dies. Erstellen Sie ein Verzeichnis mit dem Namen 'datetime' und erstellen Sie darin zwei leere Dateien, die Datei init.py (mit Unterstrichen) und datetime.py. Öffnen Sie nun einen Interpreter, importieren Sie sys und geben Sie ihn aus sys.path.insert(0, '/path/to/datetime')und ersetzen Sie diesen Pfad durch den Pfad zu dem gerade erstellten Verzeichnis. Versuchen Sie jetzt so etwas from datetime import datetime;datetime.now(). Sie sollten einen AttributeError erhalten (da jetzt Ihre leere Datei importiert wird). Wenn Sie diese Schritte wiederholen würden, ohne die leere Init-Datei zu erstellen, würde dies nicht passieren. Das soll verhindert werden.
Zwei-Bit-Alchemist
4
@ DarekNędza Sie haben etwas falsch eingerichtet, wenn Sie nicht einfach einen Python-Interpreter öffnen und from datetime import datetimeohne Fehler ausgeben können. Das ist gut bis zur Version 2.3!
Die genannten Dateien __init__.pywerden verwendet, um Verzeichnisse auf der Festplatte als Python-Paketverzeichnisse zu markieren. Wenn Sie die Dateien haben
mydir/spam/__init__.py
mydir/spam/module.py
und mydirist auf Ihrem Weg, können Sie den Code in module.pyas importieren
import spam.module
oder
from spam import module
Wenn Sie die entfernen __init__.py Datei , sucht Python nicht mehr nach Submodulen in diesem Verzeichnis, sodass Versuche, das Modul zu importieren, fehlschlagen.
Die __init__.pyDatei ist normalerweise leer, kann jedoch verwendet werden, um ausgewählte Teile des Pakets unter einem bequemeren Namen zu exportieren, Komfortfunktionen zu speichern usw. Im obigen Beispiel kann auf den Inhalt des Init-Moduls zugegriffen werden als
Update: Die Datei __init__.pywar unter Python 2.X erforderlich und wird weiterhin unter Python 2.7.12 benötigt (ich habe sie getestet), wird jedoch ab (angeblich) Python 3.3 nicht mehr benötigt und ist unter Python 3.4.3 (I) nicht mehr erforderlich getestet). Weitere Informationen finden Sie unter stackoverflow.com/questions/37139786 .
Rob_before_edits
4
Benutze es nicht. Es ist ein "Namespace" -Paket, kein reguläres Paket. Das Namespace-Paket wird für sehr seltene Anwendungsfälle verwendet. Möglicherweise müssen Sie nicht wissen, wann Sie es verwenden. Einfach benutzen __init__.py.
Methan
2
Wenn Sie jedoch haben setup.pyund verwenden find_packages(), ist es notwendig, __init__.pyin jedem Verzeichnis zu haben . Siehe stackoverflow.com/a/56277323/7127824
techkuz
484
Zusätzlich ein Verzeichnis als Python - Paket Beschriftung und definieren __all__, __init__.pykönnen Sie eine beliebige Variable auf Paketebene definieren.Dies ist häufig praktisch, wenn ein Paket etwas definiert, das häufig auf API-ähnliche Weise importiert wird. Dieses Muster fördert die Einhaltung der pythonischen Philosophie "Wohnung ist besser als verschachtelt".
Ein Beispiel
Hier ist ein Beispiel aus einem meiner Projekte, in das ich häufig einen sessionmakerAufruf importiere , Sessionum mit meiner Datenbank zu interagieren. Ich habe ein "Datenbank" -Paket mit einigen Modulen geschrieben:
import os
from sqlalchemy.orm import sessionmaker
from sqlalchemy import create_engine
engine = create_engine(os.environ['DATABASE_URL'])Session= sessionmaker(bind=engine)
Da ich Sessionhier definiere , kann ich eine neue Sitzung mit der folgenden Syntax starten. Dieser Code wird von innerhalb oder außerhalb des Paketverzeichnisses "Datenbank" ausgeführt.
from database importSession
session =Session()
Dies ist natürlich eine kleine Annehmlichkeit - die Alternative wäre, Sessionin einer neuen Datei wie "create_session.py" in meinem Datenbankpaket zu definieren und neue Sitzungen zu starten, indem Sie:
from database.create_session importSession
session =Session()
Weiterführende Literatur
Es gibt einen ziemlich interessanten reddit-Thread, der die entsprechenden Verwendungszwecke von __init__.pyhier abdeckt :
Die Mehrheitsmeinung scheint zu sein, dass __init__.pyDateien sehr dünn sein sollten, um einen Verstoß gegen die Philosophie "explizit ist besser als implizit" zu vermeiden.
engine, sessionmaker, create_engine, Und osalle auch importiert werden kann databasejetzt ... scheint , wie Sie ein Durcheinander von diesem Namensraum vorgenommen haben.
ArtOfWarfare
9
@ArtOfWarfare können Sie verwenden, um __all__ = [...]zu begrenzen, mit was importiert wird import *. Abgesehen davon bleibt Ihnen ein unordentlicher Namespace der obersten Ebene.
Nathan Gould
Darf ich wissen, wie lautet die 'DATABASE URL'? Ich habe versucht, dies zu replizieren, indem ich die create_engine mit 'mysql + mysqldb: // root: python @ localhost: 3306 / test' eingeschlossen habe, aber es funktioniert nicht. Vielen Dank.
SunnyBoiz
2
Wie würden Sie von innerhalb des Pakets, z. B. quieries.py , auf die in init definierte ' Session' -Klasse zugreifen?
Vldbnc
252
Es gibt 2 Hauptgründe für __init__.py
Der Einfachheit halber: Die anderen Benutzer müssen den genauen Speicherort Ihrer Funktionen in Ihrer Pakethierarchie nicht kennen.
Oh, bevor ich Ihre Antwort gelesen habe, dachte ich, dass es eine gute Praxis ist, eine Funktion explizit von ihrem Standort aus aufzurufen.
Aerin
2
@Aerin es wäre besser, kurze Aussagen (oder in diesem Fall subjektive Schlussfolgerungen) nicht immer als wahr zu betrachten. Das Importieren von __init__.pykann manchmal nützlich sein, aber nicht immer.
Tobias Sette
2
Werden diese Codes zur Import- oder Laufzeit ausgeführt?
user1559897
111
Die __init__.pyDatei lässt Python Verzeichnisse, die sie enthalten, als Module behandeln.
Darüber hinaus ist dies die erste Datei, die in ein Modul geladen wird, sodass Sie damit Code ausführen können, den Sie bei jedem Laden eines Moduls ausführen möchten, oder die zu exportierenden Submodule angeben können.
Native Unterstützung für Paketverzeichnisse, für die keine __init__.pyMarkierungsdateien erforderlich sind und die sich automatisch über mehrere Pfadsegmente erstrecken können (inspiriert von verschiedenen Ansätzen von Drittanbietern für Namespace-Pakete, wie in PEP 420 beschrieben ).
In Python ist die Definition des Pakets sehr einfach. Wie bei Java sind die hierarchische Struktur und die Verzeichnisstruktur gleich. Aber Sie müssen __init__.pyin einem Paket haben. Ich werde die __init__.pyDatei mit dem folgenden Beispiel erklären :
__init__.pykann leer sein, solange es existiert. Es gibt an, dass das Verzeichnis als Paket betrachtet werden sollte. Natürlich __init__.pykann auch der entsprechende Inhalt eingestellt werden.
Wenn wir eine Funktion in module_n1 hinzufügen:
def function_X():print"function_X in module_n1"return
Nach dem Rennen:
>>>from package_x.subPackage_b.module_n1 import function_X
>>>function_X()
function_X in module_n1
Dann folgten wir dem Hierarchiepaket und nannten die Funktion module_n1. Wir können __init__.pyin subPackage_b Folgendes verwenden:
__all__ =['module_n2','module_n3']
Nach dem Rennen:
>>>from package_x.subPackage_b import*>>>module_n1.function_X()Traceback(most recent call last):File"<stdin>", line 1,in<module>ImportError:No module named module_n1
Bei Verwendung des * Imports unterliegt das Modulpaket daher dem __init__.pyInhalt.
Wie sieht meine setup.py aus, um denselben Import über die gepackte Bibliothek durchzuführen? from package_x.subPackage_b.module_n1 import function_X
Technazi
Der Schlüssel zum Mitnehmen lautet also "Verwenden von * Importieren, Modulpaket unterliegt dem Inhalt von init .py"
Minnie
54
Obwohl Python ohne __init__.pyDatei funktioniert , sollten Sie dennoch eine einschließen.
Es gibt an, dass ein Paket als Modul behandelt werden soll. Fügen Sie es daher hinzu (auch wenn es leer ist).
Es gibt auch einen Fall, in dem Sie tatsächlich eine __init__.pyDatei verwenden können:
Stellen Sie sich vor, Sie hätten die folgende Dateistruktur:
main_methods
|- methods.py
Und methods.pyenthielt dies:
def foo():return'foo'
Zur Verwendung foo()benötigen Sie eine der folgenden Möglichkeiten :
from main_methods.methods import foo # Call with foo()from main_methods import methods # Call with methods.foo()import main_methods.methods # Call with main_methods.methods.foo()
Vielleicht müssen (oder möchten) Sie dort methods.pydrinnen bleiben main_methods(z. B. Laufzeiten / Abhängigkeiten), aber Sie möchten nur importieren main_methods.
Wenn Sie den Namen von methods.pyin geändert haben , können __init__.pySie foo()Folgendes verwenden main_methods:
import main_methods
print(main_methods.foo())# Prints 'foo'
Dies funktioniert, weil __init__.pyes als Teil des Pakets behandelt wird.
Einige Python-Pakete tun dies tatsächlich. Ein Beispiel ist JSON , bei dem das Ausführen import jsontatsächlich __init__.pyaus dem jsonPaket importiert wird ( siehe die Struktur der Paketdatei hier ):
Es erleichtert das Importieren anderer Python-Dateien. Wenn Sie diese Datei in einem Verzeichnis (z. B. Sachen) abgelegt haben, das andere py-Dateien enthält, können Sie so etwas wie import stuff.other ausführen.
root\
stuff\
other.py
morestuff\
another.py
Ohne dies __init__.pyim Verzeichnis stuff könnten Sie other.py nicht importieren, da Python nicht weiß, wo sich der Quellcode für stuff befindet, und es nicht als Paket erkennen kann.
Ich habe die gleiche Struktur in meinem Projekt (Python 3.4), aber ich bin nicht in der Lage, eine andere.py zu machen, andere.py zu sehen. Wie soll ich den Import machen? aus root.stuff andere importieren? Es funktioniert im VSCode-Debug-Modus, jedoch nicht in der Befehlszeile. Irgendwelche Ideen?
Rodrigorf
10
Eine __init__.pyDatei erleichtert den Import. Wenn eine __init__.pyin einem Paket vorhanden ist, a()kann die Funktion b.pywie folgt aus einer Datei importiert werden:
from b import a
Ohne sie können Sie jedoch nicht direkt importieren. Sie müssen den Systempfad ändern:
import sys
sys.path.insert(0,'path/to/b.py')from b import a
Was meinst du mit " Funktion a () kann aus der Datei b.py [Snippet] importiert werden ? Ohne sie können Sie jedoch nicht direkt importieren. "? Ich kann die Funktion a () aus der Datei b.py ohne __init__.py importieren.
Antworten:
Früher war es ein erforderlicher Teil eines Pakets ( altes "reguläres Paket" vor 3.3 , nicht neueres 3.3+ "Namespace-Paket"). ).
Hier ist die Dokumentation.
Klicken Sie einfach auf den Link. Er enthält ein Beispiel, weitere Informationen und eine Erläuterung der Namespace-Pakete, der Art von Paketen ohne
__init__.py
.quelle
sys.path.insert(0, '/path/to/datetime')
und ersetzen Sie diesen Pfad durch den Pfad zu dem gerade erstellten Verzeichnis. Versuchen Sie jetzt so etwasfrom datetime import datetime;datetime.now()
. Sie sollten einen AttributeError erhalten (da jetzt Ihre leere Datei importiert wird). Wenn Sie diese Schritte wiederholen würden, ohne die leere Init-Datei zu erstellen, würde dies nicht passieren. Das soll verhindert werden.from datetime import datetime
ohne Fehler ausgeben können. Das ist gut bis zur Version 2.3!builtins
listet integrierte Funktionen und Klassen auf , keine integrierten Module (vgl. Docs.python.org/3/tutorial/modules.html#the-dir-function ). Wenn Sie integrierte Module auflisten möchten , tun Sie diesimport sys; print(sys.builtin_module_names)
(vgl. Docs.python.org/3/library/sys.html#sys.builtin_module_names ).Die genannten Dateien
__init__.py
werden verwendet, um Verzeichnisse auf der Festplatte als Python-Paketverzeichnisse zu markieren. Wenn Sie die Dateien habenund
mydir
ist auf Ihrem Weg, können Sie den Code inmodule.py
as importierenoder
Wenn Sie die entfernen
__init__.py
Datei , sucht Python nicht mehr nach Submodulen in diesem Verzeichnis, sodass Versuche, das Modul zu importieren, fehlschlagen.Die
__init__.py
Datei ist normalerweise leer, kann jedoch verwendet werden, um ausgewählte Teile des Pakets unter einem bequemeren Namen zu exportieren, Komfortfunktionen zu speichern usw. Im obigen Beispiel kann auf den Inhalt des Init-Moduls zugegriffen werden alsbasierend darauf
quelle
__init__.py
war unter Python 2.X erforderlich und wird weiterhin unter Python 2.7.12 benötigt (ich habe sie getestet), wird jedoch ab (angeblich) Python 3.3 nicht mehr benötigt und ist unter Python 3.4.3 (I) nicht mehr erforderlich getestet). Weitere Informationen finden Sie unter stackoverflow.com/questions/37139786 .__init__.py
.setup.py
und verwendenfind_packages()
, ist es notwendig,__init__.py
in jedem Verzeichnis zu haben . Siehe stackoverflow.com/a/56277323/7127824Zusätzlich ein Verzeichnis als Python - Paket Beschriftung und definieren
__all__
,__init__.py
können Sie eine beliebige Variable auf Paketebene definieren.Dies ist häufig praktisch, wenn ein Paket etwas definiert, das häufig auf API-ähnliche Weise importiert wird. Dieses Muster fördert die Einhaltung der pythonischen Philosophie "Wohnung ist besser als verschachtelt".Ein Beispiel
Hier ist ein Beispiel aus einem meiner Projekte, in das ich häufig einen
sessionmaker
Aufruf importiere ,Session
um mit meiner Datenbank zu interagieren. Ich habe ein "Datenbank" -Paket mit einigen Modulen geschrieben:Mein
__init__.py
enthält den folgenden Code:Da ich
Session
hier definiere , kann ich eine neue Sitzung mit der folgenden Syntax starten. Dieser Code wird von innerhalb oder außerhalb des Paketverzeichnisses "Datenbank" ausgeführt.Dies ist natürlich eine kleine Annehmlichkeit - die Alternative wäre,
Session
in einer neuen Datei wie "create_session.py" in meinem Datenbankpaket zu definieren und neue Sitzungen zu starten, indem Sie:Weiterführende Literatur
Es gibt einen ziemlich interessanten reddit-Thread, der die entsprechenden Verwendungszwecke von
__init__.py
hier abdeckt :http://www.reddit.com/r/Python/comments/1bbbwk/whats_your_opinion_on_what_to_include_in_init_py/
Die Mehrheitsmeinung scheint zu sein, dass
__init__.py
Dateien sehr dünn sein sollten, um einen Verstoß gegen die Philosophie "explizit ist besser als implizit" zu vermeiden.quelle
engine
,sessionmaker
,create_engine
, Undos
alle auch importiert werden kanndatabase
jetzt ... scheint , wie Sie ein Durcheinander von diesem Namensraum vorgenommen haben.__all__ = [...]
zu begrenzen, mit was importiert wirdimport *
. Abgesehen davon bleibt Ihnen ein unordentlicher Namespace der obersten Ebene.Es gibt 2 Hauptgründe für
__init__.py
Der Einfachheit halber: Die anderen Benutzer müssen den genauen Speicherort Ihrer Funktionen in Ihrer Pakethierarchie nicht kennen.
dann können andere add () von aufrufen
ohne file1 zu kennen, wie
Wenn Sie möchten, dass etwas initialisiert wird; Zum Beispiel Protokollierung (die in die oberste Ebene gestellt werden sollte):
quelle
__init__.py
kann manchmal nützlich sein, aber nicht immer.Die
__init__.py
Datei lässt Python Verzeichnisse, die sie enthalten, als Module behandeln.Darüber hinaus ist dies die erste Datei, die in ein Modul geladen wird, sodass Sie damit Code ausführen können, den Sie bei jedem Laden eines Moduls ausführen möchten, oder die zu exportierenden Submodule angeben können.
quelle
Seit Python 3.3
__init__.py
ist es nicht mehr erforderlich, Verzeichnisse als importierbare Python-Pakete zu definieren.Überprüfen Sie PEP 420: Implizite Namespace-Pakete :
Hier ist der Test:
Referenzen:
https://docs.python.org/3/whatsnew/3.3.html#pep-420-implicit-namespace-packages
https://www.python.org/dev/peps/pep-0420/
Is __init__. py nicht erforderlich für Pakete in Python 3?
quelle
In Python ist die Definition des Pakets sehr einfach. Wie bei Java sind die hierarchische Struktur und die Verzeichnisstruktur gleich. Aber Sie müssen
__init__.py
in einem Paket haben. Ich werde die__init__.py
Datei mit dem folgenden Beispiel erklären :__init__.py
kann leer sein, solange es existiert. Es gibt an, dass das Verzeichnis als Paket betrachtet werden sollte. Natürlich__init__.py
kann auch der entsprechende Inhalt eingestellt werden.Wenn wir eine Funktion in module_n1 hinzufügen:
Nach dem Rennen:
Dann folgten wir dem Hierarchiepaket und nannten die Funktion module_n1. Wir können
__init__.py
in subPackage_b Folgendes verwenden:Nach dem Rennen:
Bei Verwendung des * Imports unterliegt das Modulpaket daher dem
__init__.py
Inhalt.quelle
from package_x.subPackage_b.module_n1 import function_X
Obwohl Python ohne
__init__.py
Datei funktioniert , sollten Sie dennoch eine einschließen.Es gibt an, dass ein Paket als Modul behandelt werden soll. Fügen Sie es daher hinzu (auch wenn es leer ist).
Es gibt auch einen Fall, in dem Sie tatsächlich eine
__init__.py
Datei verwenden können:Stellen Sie sich vor, Sie hätten die folgende Dateistruktur:
Und
methods.py
enthielt dies:Zur Verwendung
foo()
benötigen Sie eine der folgenden Möglichkeiten :Vielleicht müssen (oder möchten) Sie dort
methods.py
drinnen bleibenmain_methods
(z. B. Laufzeiten / Abhängigkeiten), aber Sie möchten nur importierenmain_methods
.Wenn Sie den Namen von
methods.py
in geändert haben , können__init__.py
Siefoo()
Folgendes verwendenmain_methods
:Dies funktioniert, weil
__init__.py
es als Teil des Pakets behandelt wird.Einige Python-Pakete tun dies tatsächlich. Ein Beispiel ist JSON , bei dem das Ausführen
import json
tatsächlich__init__.py
aus demjson
Paket importiert wird ( siehe die Struktur der Paketdatei hier ):quelle
__init__.py
behandelt das Verzeichnis, in dem es sich befindet, als ladbares Modul.Für Leute, die lieber Code lesen, habe ich hier den Kommentar von Two-Bit Alchemist eingefügt.
quelle
Es erleichtert das Importieren anderer Python-Dateien. Wenn Sie diese Datei in einem Verzeichnis (z. B. Sachen) abgelegt haben, das andere py-Dateien enthält, können Sie so etwas wie import stuff.other ausführen.
Ohne dies
__init__.py
im Verzeichnis stuff könnten Sie other.py nicht importieren, da Python nicht weiß, wo sich der Quellcode für stuff befindet, und es nicht als Paket erkennen kann.quelle
Eine
__init__.py
Datei erleichtert den Import. Wenn eine__init__.py
in einem Paket vorhanden ist,a()
kann die Funktionb.py
wie folgt aus einer Datei importiert werden:Ohne sie können Sie jedoch nicht direkt importieren. Sie müssen den Systempfad ändern:
quelle