Antworten:
Früher war es ein erforderlicher Teil eines Pakets ( altes "reguläres Paket" vor 3.3 , nicht neueres 3.3+ "Namespace-Paket"). ).
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__.py
Datei enthält. Wenn ein reguläres Paket importiert wird, wird diese__init__.py
Datei implizit ausgeführt, und die von ihr definierten Objekte werden an Namen im Namespace des Pakets gebunden. Die__init__.py
Datei 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
.
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.
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 dies import 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 haben
mydir/spam/__init__.py
mydir/spam/module.py
und mydir
ist auf Ihrem Weg, können Sie den Code in module.py
as 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__.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 als
import spam
basierend darauf
__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 verwenden find_packages()
, ist es notwendig, __init__.py
in jedem Verzeichnis zu haben . Siehe stackoverflow.com/a/56277323/7127824
Zusä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".
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:
database/
__init__.py
schema.py
insertions.py
queries.py
Mein __init__.py
enthält den folgenden Code:
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 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.
from database import Session
session = Session()
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:
from database.create_session import Session
session = Session()
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.
engine
, sessionmaker
, create_engine
, Und os
alle auch importiert werden kann database
jetzt ... scheint , wie Sie ein Durcheinander von diesem Namensraum vorgenommen haben.
__all__ = [...]
zu begrenzen, mit was importiert wird import *
. 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.
your_package/
__init__.py
file1.py
file2.py
...
fileN.py
# in __init__.py
from file1 import *
from file2 import *
...
from fileN import *
# in file1.py
def add():
pass
dann können andere add () von aufrufen
from your_package import add
ohne file1 zu kennen, wie
from your_package.file1 import add
Wenn Sie möchten, dass etwas initialisiert wird; Zum Beispiel Protokollierung (die in die oberste Ebene gestellt werden sollte):
import logging.config
logging.config.dictConfig(Your_logging_config)
__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.
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 :
Native Unterstützung für Paketverzeichnisse, für die keine
__init__.py
Markierungsdateien 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 ).
Hier ist der Test:
$ mkdir -p /tmp/test_init
$ touch /tmp/test_init/module.py /tmp/test_init/__init__.py
$ tree -at /tmp/test_init
/tmp/test_init
├── module.py
└── __init__.py
$ python3
>>> import sys
>>> sys.path.insert(0, '/tmp')
>>> from test_init import module
>>> import test_init.module
$ rm -f /tmp/test_init/__init__.py
$ tree -at /tmp/test_init
/tmp/test_init
└── module.py
$ python3
>>> import sys
>>> sys.path.insert(0, '/tmp')
>>> from test_init import module
>>> import test_init.module
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?
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 :
package_x/
|-- __init__.py
|-- subPackage_a/
|------ __init__.py
|------ module_m1.py
|-- subPackage_b/
|------ __init__.py
|------ module_n1.py
|------ module_n2.py
|------ module_n3.py
__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:
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__.py
in 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__.py
Inhalt.
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:
main_methods
|- methods.py
Und methods.py
enthielt 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.py
drinnen bleiben main_methods
(z. B. Laufzeiten / Abhängigkeiten), aber Sie möchten nur importieren main_methods
.
Wenn Sie den Namen von methods.py
in geändert haben , können __init__.py
Sie foo()
Folgendes verwenden main_methods
:
import main_methods
print(main_methods.foo()) # Prints 'foo'
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 dem json
Paket importiert wird ( siehe die Struktur der Paketdatei hier ):
Quellcode:
Lib/json/__init__.py
__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.
$ find /tmp/mydir/
/tmp/mydir/
/tmp/mydir//spam
/tmp/mydir//spam/__init__.py
/tmp/mydir//spam/module.py
$ cd ~
$ python
>>> import sys
>>> sys.path.insert(0, '/tmp/mydir')
>>> from spam import module
>>> module.myfun(3)
9
>>> exit()
$
$ rm /tmp/mydir/spam/__init__.py*
$
$ python
>>> import sys
>>> sys.path.insert(0, '/tmp/mydir')
>>> from spam import module
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ImportError: No module named spam
>>>
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__.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.
Eine __init__.py
Datei erleichtert den Import. Wenn eine __init__.py
in einem Paket vorhanden ist, a()
kann die Funktion b.py
wie 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