Frage

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

War es hilfreich?

Lösung

Es verwendet ein erforderliches Teil eines Pakets zu sein ( alt, pre -3.3 "normale Paket" , nicht neuere 3.3+ „Namespace Paket ").

Hier ist die Dokumentation.

  

Python definiert zwei Arten von Paketen, regelmäßige Pakete und Namespace-Pakete. Regelmäßige Pakete sind traditionelle Pakete, wie sie in Python 3.2 und früher existierte. Ein regelmäßiges Paket wird in der Regel als ein Verzeichnis enthält eine __init__.py-Datei implementiert. Wird ein reguläres Paket importiert wird, wird diese __init__.py Datei implizit ausgeführt, und die Objekte, die es werden Namen in dem Paket des Namespace gebunden definiert. Die __init__.py Datei denselben Python-Code enthalten kann, die andere Modul enthalten kann, und Python werden einige zusätzliche Attribute an das Modul hinzufügen, wenn es importiert wird.

Aber nur auf den Link klicken, es enthält ein Beispiel, weitere Informationen und eine Erklärung von Namespace-Paketen, die Art der Pakete ohne __init__.py.

Andere Tipps

Dateien mit dem Namen __init__.py werden als Python-Paket Verzeichnisse Verzeichnisse auf der Festplatte zu markieren. Wenn Sie die Dateien

mydir/spam/__init__.py
mydir/spam/module.py

und mydir ist auf dem Weg, können Sie den Code in module.py als

importieren
import spam.module

oder

from spam import module

Wenn Sie die __init__.py Datei entfernen, wird Python nicht länger erscheinen für Submodule in diesem Verzeichnis, so versucht das Modul zu importieren wird fehlschlagen.

Die __init__.py-Datei ist in der Regel leer, kann aber verwendet wird ausgewählte Teile des Pakets unter bequemen Namen zu exportieren, Komfortfunktionen halten, usw. Gegeben die obige Beispiel kann der Inhalt der init-Modul als

zugegriffen werden
import spam

basierend auf dieser

Neben einem Verzeichnis als Python-Paket zur Kennzeichnung und definieren __all__, __init__.py können Sie jede Variable auf Paketebene definieren. , so zu tun, ist oft praktisch, wenn ein Paket etwas definiert, die importiert werden soll Häufig in einer API artig. Dieses Muster fördert die Einhaltung der Pythonic „flach ist besser als verschachtelte“ Philosophie.

Ein Beispiel

Hier

ist ein Beispiel von einem meiner Projekte, in denen ich häufig ein sessionmaker genannt Session importieren mit meiner Datenbank zu interagieren. Ich schrieb eine „Datenbank“ -Paket mit wenigen Modulen:

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 definieren, kann ich unter einer neuen Sitzung mit der Syntax starten. Dieser Code wäre das gleiche von innerhalb oder außerhalb des „Datenbank“ Paketverzeichnisses ausgeführt werden.

from database import Session
session = Session()

Natürlich ist dies eine kleine Bequemlichkeit - die Alternative wäre Session in einer neuen Datei wie „create_session.py“ in meinem Datenbank-Paket zu definieren und neue Sitzungen beginnen mit:

from database.create_session import Session
session = Session()

Weiterführende Literatur

Es ist eine ziemlich interessante reddit Umspinnung geeignete Verwendungen von __init__.py hier:

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

Die Mehrheit Meinung scheint, dass __init__.py Dateien zu sein sollten sehr dünn sein, die „explicit ist besser als implizite“ zu vermeiden verletzen Philosophie.

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

  1. Für die Bequemlichkeit. Die anderen Benutzer nicht brauchen, um Ihre Funktionen der genauen Standort in Ihrer Pakethierarchie 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 nennen add () von

    from your_package import add
    

    ohne file1 zu wissen, wie

    from your_package.file1 import add
    
  2. Wenn Sie etwas wollen, initialisiert werden; beispielsweise die Anmeldung (die in der obersten Ebene gelegt werden soll):

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

Die __init__.py Datei macht Python behandeln Verzeichnisse als Module enthalten.

Darüber hinaus ist dies die erste Datei in einem Modul geladen werden, so können Sie diesen Code ausführen, die Sie jedes Mal, wenn ein Modul ausgeführt werden sollen geladen wird, oder geben Sie die Submodule exportiert werden.

Da Python 3.3 wird __init__.py nicht mehr benötigten Verzeichnisse wie importierbar Python-Pakete zu definieren.

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

  

Native Unterstützung für Paket-Verzeichnisse, die mehrere Pfadsegmente automatisch umspannen nicht __init__.py Marker-Dateien benötigen und (inspiriert von verschiedenen Dritt Ansätzen zum Namespace-Paketen, wie 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 nicht für Pakete in Python 3 erforderlich?

In Python die Definition der Verpackung ist sehr einfach. Wie Java ist die hierarchische Struktur und die Verzeichnisstruktur gleich. Aber Sie müssen haben __init__.py in einem Paket. Ich werde die __init__.py Datei mit dem Beispiel erläutert unter:

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 zeigt an, dass das Verzeichnis sollte als Paket betrachtet werden. Natürlich __init__.py auch die entsprechenden Inhalte einstellen können.

Wenn wir eine Funktion in module_n1 hinzufügen:

def function_X():
    print "function_X in module_n1"
    return

Nach dem Lauf:

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

function_X in module_n1 

Dann folgten wir der Hierarchie Paket und module_n1 die Funktion aufgerufen. Wir können __init__.py in subPackage_b wie folgt verwenden:

__all__ = ['module_n2', 'module_n3']

Nach dem Lauf:

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

Verwendung Daher * Importieren, Modulpaket unterliegt Inhalt __init__.py.

Obwohl Python ohne __init__.py Datei funktioniert, sollten Sie noch ein enthalten.

Es gibt ein Paket sollte als Modul behandelt werden, so deshalb sind sie (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 hatte die folgende Dateistruktur:

main_methods 
    |- methods.py

Und methods.py enthalten diese:

def foo():
    return 'foo'

So verwenden foo() Sie eine der folgenden Optionen benötigen würde:

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 gibt müssen Sie (oder wollen) methods.py innerhalb main_methods (Runtimes / Abhängigkeiten zum Beispiel) zu halten, aber Sie wollen nur main_methods importieren.


Wenn Sie verändert den Namen methods.py __init__.py dann könnte man foo() nur durch den Import main_methods verwenden:

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

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


Einige Python-Pakete tatsächlich tun. Ein Beispiel ist mit JSON , wo tatsächlich läuft import json __init__.py vom json Paket importiert ( die Paketdatei Struktur hier ):

  

Der Quellcode: Lib/json/__init__.py

__init__.py behandeln wird das Verzeichnis es in als ladbares Modul ist.

Für Menschen, den Code lieber lesen, habe ich Two-Bit Alchimisten Kommentar hier.

$ 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 andere Python-Dateien importieren. Wenn Sie diese Datei in einem Verzeichnis abgelegt (sagen Sachen) andere py-Dateien enthalten, können Sie so etwas wie Import stuff.other tun.

root\
    stuff\
         other.py

    morestuff\
         another.py

Ohne diese __init__.py im Verzeichnis Sachen, können Sie nicht importieren other.py, weil Python nicht weiß, wo der Quellcode für Material und kann es nicht als Paket erkennen.

Eine __init__.py Datei macht Importe leicht. Wenn ein __init__.py in einem Paket vorhanden ist, Funktion a() kann wie so aus Datei b.py importiert werden:

from b import a

Ohne sie können Sie jedoch nicht direkt importieren. Sie haben den Systempfad zu ändern:

import sys
sys.path.insert(0, 'path/to/b.py')

from b import a
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top