wake-up-neo.com

Wofür ist __init__.py?

Wozu dient __init__.py in einem Python Quellverzeichnis?

1947
Mat

Früher war es ein erforderlicher Teil eines Pakets ( altes "reguläres Paket" vor Version 3. , nicht neueres "Namespace-Paket" ab Version 3. ).

Hier ist die Dokumentation.

Python definiert zwei Arten von Paketen: reguläre Pakete und Namespace-Pakete. Reguläre Pakete sind traditionelle Pakete, wie sie in Python 3.2 und früher existierten. 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 sind an Namen im Namespace des Pakets gebunden. Die __init__.py -Datei kann denselben Python -Code enthalten wie jedes andere Modul, 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, die Art der Pakete ohne __init__.py.

1267
Loki

Dateien mit dem Namen __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 Pfad, können Sie den Code in module.py als importieren

import spam.module

oder

from spam import module

Wenn Sie die Datei __init__.py entfernen, sucht Python nicht mehr nach Submodulen in diesem Verzeichnis, sodass der Versuch, das Modul zu importieren, fehlschlägt.

Die __init__.py -Datei ist normalerweise leer, kann jedoch zum Exportieren ausgewählter Teile des Pakets unter einem günstigeren Namen, mit praktischen Funktionen usw. verwendet werden. In dem obigen Beispiel kann auf den Inhalt des Init-Moduls zugegriffen werden als

import spam

basierend auf this

736
caritos

Neben der Kennzeichnung eines Verzeichnisses als Python -Paket und der Definition von __all__ können Sie mit __init__.py beliebige Variablen auf Paketebene definieren. Dies ist oft praktisch, wenn ein Paket etwas definiert, das auf API-ähnliche Weise häufig importiert wird. Dieses Muster fördert die Einhaltung der pythonischen Philosophie "Besser flach als verschachtelt".

Ein Beispiel

Hier ist ein Beispiel aus einem meiner Projekte, in dem ich häufig ein sessionmaker namens Session importiere, um mit meiner Datenbank zu interagieren. Ich habe ein "Datenbank" -Paket mit ein paar 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 hier Session definiere, kann ich eine neue Sitzung mit der folgenden Syntax starten. Dieser Code wird gleichermaßen innerhalb oder außerhalb des Paketverzeichnisses "database" ausgeführt.

from database import Session
session = Session()

Dies ist natürlich ein kleiner Vorteil - 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 Folgendes verwenden:

from database.create_session import Session
session = Session()

Weitere Lektüre

Es gibt einen ziemlich interessanten Reddit-Thread, der die entsprechenden Verwendungen von __init__.py hier behandelt:

http://www.reddit.com/r/Python/comments/1bbbwk/whats_your_opinion_on_what_to_include_in_init_py/

Die Mehrheit scheint der Meinung zu sein, dass __init__.py -Dateien sehr dünn sein sollten, um eine Verletzung der Philosophie "Explizit ist besser als implizit" zu vermeiden.

438
Nathan Gould

Es gibt 2 Hauptgründe für __init__.py

  1. Der Einfachheit halber: Die anderen Benutzer müssen die genaue Position 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
    
  2. Wenn Sie möchten, dass etwas initialisiert wird; Beispiel: Protokollierung (sollte in die oberste Ebene gestellt werden):

    import logging.config
    logging.config.dictConfig(Your_logging_config)
    
170
flycee

Die __init__.py -Datei veranlasst Python, Verzeichnisse, die sie enthalten, als Module zu behandeln.

Darüber hinaus ist dies die erste Datei, die in ein Modul geladen wird, sodass Sie bei jedem Laden eines Moduls Code ausführen oder die zu exportierenden Submodule angeben können.

101
Can Berk Güder

Seit Python 3.3 muss __init__.py keine Verzeichnisse mehr als importierbare Python Pakete definieren.

Überprüfen Sie PEP 420: Implizite Namespace-Pakete :

Native Unterstützung für Paketverzeichnisse, die keine __init__.py Markierungsdateien erfordern und sich automatisch über mehrere Pfadsegmente erstrecken können (inspiriert von verschiedenen Ansätzen von Drittanbietern für Namespace-Pakete, wie in PEP 42 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

verweise:
https://docs.python.org/3/whatsnew/3.3.html#pep-420-implicit-namespace-packages
https://www.python.org/dev/peps/pep-0420/
Wird __init__.py nicht für Pakete in Python 3 benötigt?

78
zeekvfu

In Python ist die Definition von package sehr einfach. Wie bei Java sind die hierarchische Struktur und die Verzeichnisstruktur identisch. Aber Sie müssen __init__.py in einem Paket haben. Ich erkläre die __init__.py -Datei anhand des folgenden Beispiels:

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 soll. Natürlich kann __init__.py 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 Rennen:

>>>from package_x.subPackage_b.module_n1 import function_X
>>>function_X()

function_X in module_n1 

Dann folgten wir dem Hierarchiepaket und riefen die Funktion module_n1 auf. Wir können __init__.py in subPackage_b wie folgt 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

Wenn Sie * importieren, unterliegt das Modulpaket dem Inhalt von __init__.py.

51
Marcus Thornton

Obwohl Python ohne __init__.py -Datei funktioniert, sollten Sie dennoch eine einfügen.

Es gibt an, dass ein Paket als Modul behandelt werden soll, schließen Sie es daher ein (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 Folgendes:

def foo():
    return 'foo'

Um foo() zu verwenden, 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()

Möglicherweise müssen (oder möchten) Sie methods.py in main_methods belassen (z. B. Laufzeiten/Abhängigkeiten), aber Sie möchten nur main_methods importieren.


Wenn Sie den Namen von methods.py in __init__.py geändert haben, können Sie foo() verwenden, indem Sie einfach main_methods importieren:

import main_methods
print(main_methods.foo()) # Prints 'foo'

Dies funktioniert, weil __init__.py als Teil des Pakets behandelt wird.


Einige Python -Pakete tun dies tatsächlich. Ein Beispiel ist mit JSON , wobei beim Ausführen von import json tatsächlich __init__.py aus dem json -Paket importiert wird ( siehe Struktur der Paketdatei hier ):

Quellcode: Lib/json/__init__.py

42
Simon

__init__.py behandelt das Verzeichnis, in dem es sich befindet, als ladbares Modul.

Für Leute, die es vorziehen, Code zu lesen, füge ich hier Two-Bit Alchemist's comment ein.

$ 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
>>> 
37
B.Mr.W.

Dies erleichtert das Importieren anderer python Dateien. Wenn Sie diese Datei in ein Verzeichnis (z. B. Zeug) gelegt 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 diesen __init__.py im Verzeichnis stuff konnten Sie other.py nicht importieren, da Python nicht weiß, wo sich der Quellcode für stuff befindet und es nicht als Paket erkennen kann.

28
Epitaph

Eine __init__.py -Datei erleichtert den Import. Wenn ein __init__.py in einem Paket vorhanden ist, kann die Funktion a() wie folgt aus der Datei b.py 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
5
Alec Alameddine