2013-11-27 7 views
9

Ho una directory con un pacchetto python come segue:Sphinx e relative importazioni in Python 3. *

--docs/index.rst 
--docs/... 
--app/__init__.py 
--app/foo.py 

e sto usando sfinge con autodocs per documentare l'applicazione (in python 3.3).

Ora, nel conf.py (all'interno docs/), ho

sys.path.insert(0, os.path.abspath('../app')) 

ho cd in docs/, eseguire

make html 

che mi dà

SystemError: modulo Parent '' non caricato, impossibile eseguire l'importazione relativa

a tutti i moduli che hanno un

from .foo import Bar 

Ho un'installazione pulita di virtualenv Sfinge usando

pip install Sphinx 

dopo che ho creato l'ambiente (pulito) per Python 3.3.

Cosa mi manca?

Stavo spostando il progetto da python 2. * a python 3. * quando questo è successo. Tutto il progetto funziona, ma questo ...

+0

È 'app' un pacchetto di livello superiore stesso o la directory in cui si trovano i pacchetti di livello superiore? – abarnert

+0

Non sono sicuro di aver capito la tua domanda @abarnert. 'app' non ha una directory all'interno, solo un insieme di' * .py', incluso '__init __. py'. sfinge solo documenti app dir. –

+0

Se 'app' ha' __init __. Py' dentro, allora è un pacchetto. E questo è il tuo problema. Lasciami scrivere una risposta per spiegare. – abarnert

risposta

14

La tua directory app è un pacchetto. Un pacchetto è una directory con __init.py__ e altri file al suo interno.

Se si inserisce una directory di pacchetto sul proprio sys.path, tutti i tipi di cose vanno male.

Facciamo un esempio:

root/ 
    app/ 
     app/__init__.py 
     app/spam.py 
     app/eggs.py 

Se avete root sul sys.path (perché è la directory di lavoro corrente, o perché lo si fa in modo esplicito, o perché hai installato le cose correttamente il tuo site-packages), quindi app è un pacchetto, app.spam è un modulo e, all'interno di app.eggs, il modulo è .spam. Quindi, tutto funziona.

Se avete app sul sys.path, allora app non è un pacchetto, spam è un modulo, e, all'interno di eggs, .spam non è nulla. Quindi, non puoi usare le importazioni relative.

Se hai sia sul sys.path, poi app è un pacchetto, spam e app.spam sono entrambi diversi moduli (con lo stesso contenuto, eseguiti due volte), ed entro app.eggs, .spam è un modulo, ma all'interno eggs, .spam non è nulla. Ciò ti causerà la fine dei problemi.


Quindi, molto probabilmente, la correzione che si desidera è questo:

sys.path.insert(0, os.path.abspath('..')) 

Se ci sono altri pacchetti, o directory piene di codice Python che non sono pacchetti, in .. che don' t vuole AutoDoc (ad esempio, una directory tests con tests/test_spam.py), allora si avrà bisogno di ristrutturare le directory di mettere app in qualche directory che non ha nessun altro codice Python in esso, come questo:

root/ 
    src/ 
     app/ 
    tests/ 
    doc/ 

In alternativa, se non volevi app per essere un pacchetto, ma piuttosto da una directory principale sys.path, poi uccidere il __init__.py, e lasciare app direttamente in sys.path. In tal caso, non è possibile utilizzare le importazioni relative all'interno del pacchetto; tutti i moduli in app sono moduli di livello superiore e devono essere importati come tali.


La sezione Packages del tutorial (e il resto del capitolo sopra di esso) spiega alcune di queste, ma c'è probabilmente una migliore documentazione introduttivo là fuori.

Per tutti i dettagli, in 3.3+, The import system ha tutto, ben organizzato; per le versioni precedenti, i documenti di riferimento sono fangosi, incompleti e dispersi; devi iniziare da The import statement e quindi leggere The Knights Who Say Neeeow ... Wum ... Ping! (che è fondamentalmente un PEP ma 1.5 non aveva ancora PEP), e forse anche la documentazione ni, se puoi trovarla, oltre a vari PEP e minori voci del registro delle modifiche che spiegano come sono cambiate le cose tra 1.5 e 2.7 o 3.2 o qualsiasi altra cosa.

+0

Ottima risposta. Grazie. Mi hai fatto capire che ho molto da imparare sul nuovo sistema. –

+2

@ J.C.Leitão: Se si stesse facendo la stessa cosa in Python 2.x, era sbagliato anche lì. È solo che 2.7 ti permette di liberarti di scrivere cose che sono a metà strada tra lo stile Python 1.5 e Python-3.3 e a volte funziona ... – abarnert