Was ist __init__.py
für in einem Python-Quellverzeichnis?
Es ist ein "Namespace"-Paket. Verwenden Sie es nicht für normale Pakete.
Was ist __init__.py
für in einem Python-Quellverzeichnis?
Seit Python 3.3, __init__.py
ist nicht mehr erforderlich, um Verzeichnisse als importierbare Python-Pakete zu definieren.
Siehe PEP 420: Implizite Namespace-Pakete :
Native Unterstützung für Paketverzeichnisse, die keine
__init__.py
Markierungsdateien und kann automatisch mehrere Pfadsegmente umfassen (inspiriert durch verschiedene Ansätze von Drittanbietern für Namespace-Pakete, wie beschrieben in PEP 420 )
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/
Ist __init__.py für Pakete in Python 3 nicht erforderlich?
Obwohl Python auch ohne ein __init__.py
Datei sollten Sie trotzdem eine einfügen.
Er gibt an, dass das Verzeichnis wie ein Paket behandelt werden soll, also einzuschließen ist (auch wenn es leer ist).
Es gibt auch einen Fall, in dem Sie tatsächlich eine __init__.py
Datei:
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 einen der folgenden Punkte:
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 wollen) Sie dort die methods.py
innerhalb main_methods
(z.B. Laufzeiten/Abhängigkeiten), aber Sie wollen nur die main_methods
.
Wenn Sie den Namen von methods.py
a __init__.py
dann könnten Sie foo()
durch einfaches Importieren main_methods
:
import main_methods
print(main_methods.foo()) # Prints 'foo'
Dies funktioniert, weil __init__.py
wird als Teil des Pakets behandelt.
Einige Python-Pakete tun dies tatsächlich. Ein Beispiel ist mit JSON , wobei das Laufen import json
tatsächlich importiert __init__.py
von der json
Paket ( siehe die Struktur der Paketdateien hier ):
Quellcode:
Lib/json/__init__.py
In Python ist die Definition eines Pakets sehr einfach. Wie bei Java sind die hierarchische Struktur und die Verzeichnisstruktur dieselben. Aber Sie müssen __init__.py
in einem Paket. Ich erkläre die __init__.py
Datei mit dem unten stehenden Beispiel:
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 sie existiert. Es zeigt an, dass das Verzeichnis als Paket betrachtet werden soll. Ja, natürlich, __init__.py
kann auch den entsprechenden Inhalt einstellen.
Wenn wir eine Funktion in module_n1 hinzufügen:
def function_X():
print "function_X in module_n1"
return
Nach dem Laufen:
>>>from package_x.subPackage_b.module_n1 import function_X
>>>function_X()
function_X in module_n1
Dann folgen wir dem Hierarchiepaket und rufen die Funktion module_n1 auf. Wir können verwenden __init__.py
in subPackage_b wie folgt:
__all__ = ['module_n2', 'module_n3']
Nach dem Laufen:
>>>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
Daher unterliegt ein * importiertes Modulpaket den __init__.py
Inhalt.
__init__.py
behandelt das Verzeichnis, in dem es sich befindet, wie ein ladbares Modul.
Für Leute, die lieber Code lesen, habe ich Two-Bit Alchemist's hier kommentieren.
$ 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 den Import von anderen Python-Dateien. Wenn Sie diese Datei in einem Verzeichnis (z.B. stuff) platzieren, das andere py-Dateien enthält, dann können Sie so etwas wie import stuff.other machen.
root\
stuff\
other.py
morestuff\
another.py
Ohne diese __init__.py
innerhalb des Verzeichnisses stuff können Sie other.py nicht importieren, da Python nicht weiß, wo der Quellcode von stuff liegt und es nicht als Paket erkennen kann.
CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.
36 Stimmen
Gemäß dem unten stehenden Kommentar von @Rob_before_edits und dieser Stackoverflow-Thread 37139786 scheint es, dass init .py wird für Python 3.3+ nicht mehr benötigt.
24 Stimmen
Paket ohne
__init__
es Namensraum Paket , nicht ein normales Paket . Das ist nicht dasselbe wie @methane mit hier ein Beispiel .4 Stimmen
@Rainning Ein Namespace-Paket unterscheidet sich nicht grundlegend von einem normalen Paket. Es ist nur eine andere Art, Pakete zu erstellen. Sobald ein Namespace-Paket erstellt ist, gibt es keinen funktionalen Unterschied mehr zwischen ihm und einem regulären Paket.
1 Stimmen
Die offiziellen Dokumente enthalten eine Reihe von Artikeln, in denen die Verwendung des Begriffs erklärt wird, und sie definieren auch jeden Begriff genau.
4 Stimmen
@Rainning vielleicht haben Sie nicht bemerkt, dass die Erklärung, die ich oben hinzugefügt habe, wortwörtlich von pep420 stammt
1 Stimmen
@Jun711: Haben Sie den Link gelesen, den ich angegeben habe? Womit ich nicht einverstanden bin, ist ein Kommentar, der hoch gevotet wurde, aber eigentlich falsch ist. Du empfiehlst Leuten, die Python lernen, zu denken, dass
__init__.py
war nutzlos und kann vollständig ignoriert werden (Sie sagten "nicht mehr benötigt").