2014-06-19 12 views
7

Ich lerne Python, und ich kann nicht herausfinden, wie Importe in __init__.py arbeiten.Python Submodul importiert mit __init__.py

Ich verstehe von the Python tutorial, dass die Datei __init__.py ein Paket initialisiert, und dass ich hier Unterpakete importieren kann.

Ich mache etwas falsch. Kannst du mir (und zukünftigen Python-Lernern) erklären, was ich falsch mache?

Hier ist ein vereinfachtes Beispiel, was ich versuche zu tun.

Dies ist meine Dateistruktur:

package 
    __init__.py 
    test.py 
    subpackage 
     __init__.py 
     hello_world.py 

Der Inhalt hello_world.py:

def do_something(): 
    print "Hello, world!" 

subpackage/__init__.py ist leer.

package/__init__.py enthält:

import test.submodule.do_something 

Und schließlich test.py enthält:

do_something() 

Dies ist, wie ich versuche, mit laufen hello_world.py OSX Terminal und Python 3:

python test.py 

Python löst dann den folgenden Fehler aus:

NameError: name 'do_something' is not defined 
+0

Ich nehme an, das 'test.py', das Sie ausführen, ist' package/test.py'? Wenn das der Fall ist, muss ich nicht sehen, dass es sich in einem Paket befindet, und so scheint 'package/__ init __. Py' völlig irrelevant zu sein. – holdenweb

Antwort

10

Wahrscheinlich haben Sie bereits verstanden, dass der Interpreter beim Importieren eines Moduls einen neuen Namespace erstellt und den Code dieses Moduls mit dem neuen Namespace als lokalen und globalen Namespace ausführt. Wenn der Code die Ausführung abschließt, wird der Modulname (oder der in einer beliebigen as-Klausel angegebene Name) an das gerade im importierenden Namespace erstellte Modulobjekt gebunden.

Die __init__.py in einem Paket dient weitgehend die gleiche Funktion. Ein Paket mit Struktur wird als ein Verzeichnis geschrieben, das auch Module (reguläre .py Dateien) und Unterverzeichnisse (die auch eine __init__.py Datei enthalten müssen) für beliebige Unterpakete enthält. Wenn das Paket importiert wird, wird ein neuer Namespace erstellt, und __init__.py des Pakets wird mit diesem Namespace als lokaler und globaler Namespace ausgeführt. Um Ihr Problem zu lösen, können wir Ihren Dateispeicher entfernen, indem Sie das Paket der obersten Ebene weglassen, das vom Interpreter nie berücksichtigt wird, wenn test.py als Programm ausgeführt wird. Es würde dann wie folgt aussehen:

test.py 
subpackage/ 
    __init__.py 
    hello_world.py 

Nun subpackage ist nicht länger ein Unterpaket, wie wir das Paket enthält, als irrelevant entfernt haben. Konzentrieren Sie sich darauf, warum der Name do_something nicht definiert ist. test.py enthält keinen Import, und daher ist unklar, wie Sie erwarten, do_something Bedeutung zu erwerben. Man könnte es mit Hilfe eines leeren subpackage/__init__.py funktioniert und test.py könnte dann lesen Sie

from subpackage.hello_world import do_something 
do_something() 

Alternativ könnte uns ein subpackage/__init__.py die

from hello_world import do_something 

liest, die die do_something Funktion innerhalb des subpackage Namensraum einrichtet, wenn das Paket importiert.Dann ein test.py verwenden, die die Funktion aus dem Paket importiert, wie folgt aus:

from subpackage import do_something 
do_something() 

Eine letzte Alternative mit den gleichen __init__.py ist ein test.py zu verwenden, die einfach importiert das (sub) Paket und dann relativ Namensgebung verwenden, um den Zugriff auf gewünschte Funktion:

import subpackage 
subpackage.do_something() 

in Ihrem lokalen Namespace den Zugriff darauf zu gewinnen

mit dem leeren __init__.py Dies könnte auch mit einem test.py rea erreicht werden

ding
import subpackage.hello_world 
subpackage.hello_world.do_something() 

oder sogar

from subpackage.hello_world import do_something 
do_something() 

letztlich das beste Werkzeug, das Sie gerade zu halten ist ein klares Verständnis davon, wie Import funktioniert und was Wirkung seinen verschiedenen Formen auf dem Import Namespace haben.

+0

Ah, ich denke ich verstehe jetzt. Mein Fehler war zu denken, dass "import" ähnlich wie "include" in PHP oder C funktioniert, und dass __init__.py Code war, der immer ausgeführt würde, bevor ein Paket verwendet wurde. Danke für die tolle Antwort. – Benjamin

+0

Ein Vergnügen, und ich bin froh, dass es geholfen hat. Ich unterrichte dieses Zeug für meinen Lebensunterhalt, aber wenn ich nicht zu beschäftigt bin, ist es toll, der Community wieder beizutreten und Leuten zu helfen – holdenweb

+1

Ich vermute, dass das Importieren eines Moduls als Unterpaket oder von einem Unterpaket zum Importieren des Untermoduls führen kann -Paket zweimal: import subpackage.hello_world importiert das Unterpaket erneut, selbst wenn eine andere Importanweisung das Unterpaket importiert. Ich denke, die Google Python Coding-Richtlinie erwähnt dies kurz, https://google-styleguide.googlecode.com/svn/trunk/pyguide.html?showone=Packages#Packages –

1

Zuerst müssen Sie verstehen, wie import allein Arbeit:

import test.submodule.do_something 

versuchen würde do_something von submodule selbst von test geladen zu laden.

Sie wollen von subpackage etwas zu laden, so beginnen mit, dass:

import subpackage 

Fein, subpackage/__init__.py geladen wird.

Jetzt wollen Sie die do_something() Funktion, die in der Datei (ein "Modul") ist hello_world.py. Einfach:

from subpackage.hello_world import do_something 

Und Sie sind fertig! Lesen Sie einfach diese Zeile laut, es tut genau das, was es sagt: Importieren Sie do_something aus dem Modul hello_world, das in dem subpackage Paket ist.

Versuchen Sie das mal in test.py

from subpackage.hello_world import do_something 

do_something() 

Es sollte gut funktionieren.

nun die zweite Ausgabe:

__init__.py nicht in package/ genannt werden, da Sie nicht package/ als Paket verwenden Sie. __init__.py wird verwendet, wenn Sie in ihm einen Import von package/ oder irgendetwas tun, zum Beispiel:

from package import test 

Ansonsten wird es nicht geladen werden.

Wenn Sie jedoch do_something() auf den Import von subpackage laden möchten, setzen from submodule.hello_word import do_something in subpackage/__init__.py, und dann, in Sie test.py, machen einen import subpackage.

+0

Vielen Dank! Ich denke, ich verstehe es jetzt. – Benjamin

1

Es ist in Python eine absolut harte Regel, dass ein Name immer innerhalb des Moduls, in dem Sie ihn verwenden, definiert oder importiert werden muss. Hier importieren Sie nie etwas in test.py - so wie der Fehler sagt, do_something ist nicht definiert.

Auch wenn Ihre package/__init__.py Datei ausgeführt wurde (was, wie andere gezeigt haben, ist es nicht), würde Ihr Code immer noch nicht so funktionieren, da der Import von do_something innerhalb von test.py erfolgen muss wenn Sie in der Datei darauf verweisen möchten.

Verwandte Themen