3676 Stimmen

Wofür ist __init__.py da?

Was ist __init__.py für in einem Python-Quellverzeichnis?

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.

138voto

zeekvfu Punkte 3168

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?

10 Stimmen

Es ist ein "Namespace"-Paket. Verwenden Sie es nicht für normale Pakete.

2 Stimmen

@methan, könnten Sie Ihren Kommentar näher erläutern?

7 Stimmen

116voto

Xantium Punkte 10070

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

74voto

Marcus Thornton Punkte 5451

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.

0 Stimmen

Wie wird meine setup.py aussehen, um den gleichen Import durch die gepackte Bibliothek zu tun? from package_x.subPackage_b.module_n1 import function_X

0 Stimmen

Die wichtigste Erkenntnis ist also "mit * importieren, Modulpaket unterliegt init .py Inhalt"

53voto

B.Mr.W. Punkte 17636

__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
>>>

44voto

Epitaph Punkte 3052

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.

2 Stimmen

Ich habe die gleiche Struktur in meinem Projekt (Python 3.4), aber ich bin nicht in der Lage, another.py sehen other.py zu machen. Wie sollte ich den Import vornehmen? from Root.stuff import other? Es funktioniert im VSCode-Debug-Modus, aber nicht in der Kommandozeile. Irgendwelche Ideen?

CodeJaeger.com

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.

Powered by:

X