2014-06-19 14 views
7

Sto imparando Python e non riesco a capire come funzionano le importazioni in __init__.py.Importazione del submodulo Python utilizzando __init__.py

Capisco da the Python tutorial che il file __init__.py inizializza un pacchetto e che posso importare i pacchetti secondari qui.

Sto facendo qualcosa di sbagliato, però. Potresti spiegare per me (e per i futuri allievi di Python) cosa sto sbagliando?

Ecco un esempio semplificato di ciò che sto cercando di fare.

Questa è la mia struttura di file:

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

Il contenuto di hello_world.py:

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

subpackage/__init__.py è vuota.

package/__init__.py contiene:

import test.submodule.do_something 

E, infine, test.py contiene:

do_something() 

Questo è come si tenta di eseguire hello_world.py con il morsetto OSX e Python 3:

python test.py 

Python genera quindi il seguente errore:

NameError: name 'do_something' is not defined 
+0

Suppongo che 'test.py' sia in esecuzione' package/test.py'? Se è così, non c'è bisogno che io possa vedere perché si trovi in ​​un pacchetto, e quindi 'package/__ init __. Py' sembrerebbe del tutto irrilevante. – holdenweb

risposta

10

Probabilmente già comprendi che quando si importa un modulo , l'interprete crea un nuovo spazio dei nomi ed esegue il codice di quel modulo con il nuovo spazio dei nomi come spazio dei nomi locale e globale. Quando il codice completa l'esecuzione, il nome del modulo (o il nome dato in qualsiasi clausola as) è associato all'oggetto modulo appena creato all'interno dello spazio dei nomi di importazione.

Lo __init__.py in un pacchetto ha la stessa funzione. Un pacchetto , con struttura, è scritto come una directory che può contenere anche moduli (file regolari .py) e sottodirectory (che deve contenere anche un file __init__.py) per qualsiasi sotto_package. Quando il pacchetto viene importato, viene creato un nuovo spazio dei nomi e il pacchetto __init__.py viene eseguito con tale spazio dei nomi come spazi dei nomi locali e globali. Pertanto, per rispondere al problema, è possibile eliminare il file archivio omettendo il pacchetto di livello superiore, che non verrà mai preso in considerazione dall'interprete quando test.py viene eseguito come programma. Sarebbe quindi simile a questa:

test.py 
subpackage/ 
    __init__.py 
    hello_world.py 

Ora, subpackage non è più un sub-pacchetto, come abbiamo rimosso il pacchetto contenente come irrilevante. Concentrarsi sul perché il nome do_something non è definito potrebbe aiutare. test.py non contiene alcuna importazione, quindi non è chiaro come ti aspetti che do_something acquisisca un significato. Si potrebbe farlo funzionare utilizzando un vuoto subpackage/__init__.py e poi test.py potrebbe leggere

from subpackage.hello_world import do_something 
do_something() 

In alternativa si potrebbe noi una subpackage/__init__.py che legge

from hello_world import do_something 

che stabilisce la funzione do_something all'interno della subpackage spazio dei nomi quando il pacchetto è importato.Quindi utilizzare un test.py che importa la funzione dal pacchetto, in questo modo:

from subpackage import do_something 
do_something() 

Un'alternativa finale con la stessa __init__.py è usare un test.py che importa semplicemente il pacchetto (sub) e quindi usare relativa denominazione per accedere funzione richiesta:

import subpackage 
subpackage.do_something() 

per ottenere l'accesso ad esso nello spazio dei nomi locale

con il vuoto __init__.py questo potrebbe anche essere realizzato con un test.py rea ding

import subpackage.hello_world 
subpackage.hello_world.do_something() 

o anche

from subpackage.hello_world import do_something 
do_something() 

In definitiva lo strumento migliore per tenervi retta è una chiara comprensione di come funziona importazione e che effetto le sue varie forme hanno sul namespace importazione.

+0

Ah, penso di capire adesso. Il mio errore era pensare che "import" funzionasse in modo simile a "include" in PHP o C, e che __init__.py fosse un codice che sarebbe sempre eseguito prima che un pacchetto venisse usato. Grazie per la magnifica risposta. – Benjamin

+0

Un piacere, e sono contento che sia stato d'aiuto. Insegno questa roba per vivere, ma quando non sono troppo occupato è bello riunirmi alla comunità e aiutare la gente fuori – holdenweb

+1

Ho il sospetto che l'importazione di un modulo come sottoprogetto o da un sotto-pacchetto possa portare all'importazione del sottomarino -package twice: import subpackage.hello_world reimporta il subpackage anche quando un altro import import ha importato il subpackage. Immagino che la linea guida per la codifica Python di Google ne citi brevemente, https://google-styleguide.googlecode.com/svn/trunk/pyguide.html?showone=Packages#Packages –

1

In primo luogo, è necessario capire come import solo lavoro:

import test.submodule.do_something 

avrebbe cercato di caricare do_something da submodule sé caricato da test.

si desidera caricare qualcosa da subpackage, in modo da iniziare con quel:

import subpackage 

raffinata, subpackage/__init__.py viene caricato.

Ora, si desidera la funzione do_something() che si trova nel file (un "modulo") hello_world.py. Facile:

from subpackage.hello_world import do_something 

Ed è fatta! Basta leggere questa linea ad alta voce, fa esattamente quello che dice: importare do_something dal modulo hello_world che si trova nel pacchetto subpackage.

Prova che nel test.py

from subpackage.hello_world import do_something 

do_something() 

Dovrebbe funzionare bene.

Ora, il secondo numero:

__init__.py non verrà chiamato in package/ dal momento che non si utilizza package/ come un pacchetto. __init__.py sarà usato se si fa l'importazione di package/ o nulla in esso, per esempio:

from package import test 

In caso contrario, non verrà caricato a tutti.

Tuttavia, se si desidera caricare do_something() sull'importazione di sottopackage, messo in from submodule.hello_word import do_somethingsubpackage/__init__.py, e poi, in voi test.py, fare un import subpackage.

+0

Grazie mille! Penso di averlo capito ora. – Benjamin

1

È una regola assoluta e dura in Python che un nome deve essere sempre definito o importato nel modulo in cui lo si utilizza. Qui non importi mai nulla all'interno di test.py - così come dice l'errore, do_something non è definito.

Anche se il file package/__init__.py è stato eseguito (che, come altri hanno sottolineato, non lo è), il codice non funzionerebbe ancora così com'è, perché l'importazione di do_something deve essere eseguita all'interno di test.py se vuoi fare riferimento in quel file.

Problemi correlati