2013-05-03 16 views
6

Quindi, ho visto alcune domande simili su Stack Overflow, ma nulla sembra risolvere il mio problema, o il caso generale. Quindi, si spera che questa domanda risolva il problema, e fermi il mio mal di testa. Ho un repo git della forma:Importazione da sottodirectory secondarie in Python?

repo/ 
    __init__.py 
    sub1/ 
     __init__.py 
     sub1a/ 
     __init.py 
     mod1.py 
    sub2/ 
     __init__.py 
     mod2.py 

Come posso importare mod2.py da mod1.py e viceversa, e in che modo questo cambiamento a seconda se mod1.py o mod2.py sono degli script (quando ciascuno di essi importa - non viene importato)?

risposta

6

La soluzione più semplice consiste nel mettere la directory contenente repo nel proprio PYTHONPATH e quindi utilizzare solo le importazioni del percorso assoluto, ad es. import repo.sub2.mod2 e così via.

Ogni altra soluzione sta per coinvolgere alcuni aggiustamenti, se si vuole che i casi in cui si sta invocando sia i file di python direttamente come script da directory arbitrari - molto probabilmente sys.path di mutilazione per compiere efficacemente la stessa cosa di impostazione PYTHONPATH, ma senza doverlo impostare dall'utente.

+1

Sto bene con la modifica di PYTHONPATH, ma c'è un modo standard per far rispettare questo? Non voglio che tutti i nuovi utenti del repository debbano entrare manualmente e aggiornare il loro PYTHONPATH. – Eli

+1

Se non si desidera che le persone debbano gestire 'PYTHONPATH' da sé, allora potrebbe essere necessario considerare il mangling di' sys.path'. (Ad esempio, usare '__file__' più 'os.abspath' per cercare dove si trova lo script, quindi ottenere la directory il giusto numero di livelli sopra di esso per essere il genitore di' repo', e quindi' sys.path.insert 'it.) – Amber

2

Se si sta utilizzando Python 2.6+, si hanno due scelte:

  • importazioni rispetto
  • Aggiunta repo al PYTHONPATH

Con le importazioni relative, una sintassi speciale di punti viene utilizzato:

nel pacchetto sub1:

from .sub2.mod2 import thing 

nel pacchetto SUB1A:

from ..sub2.mod2 import otherthing 

Nota che le dichiarazioni di importazione di pianura (import module) non funzionano con le importazioni relative.

Una soluzione migliore sarebbe utilizzando le importazioni assoluti con il percorso di Python impostato correttamente (ad esempio in bash):

export PYTHONPATH=/where/your/project/is:$PYTHONPATH 

Maggiori informazioni:

+0

Volevo davvero che queste importazioni relative funzionassero. Tuttavia, sul mio python 2.7, non funzionano. –

+0

Utilizzando Python 2.7, ho avuto successo usando istruzioni come 'from sub2.mod2 import thing'. – coralvanda

0

Uno script o modulo in grado di importare moduli che sono o

  1. nel percorso di sistema, o
  2. parte dello stesso pacchetto dello script/modulo importazione.

Per i moduli queste regole si applicano senza eccezioni. Per gli script, si applicano le regole, ma la ruga è che per impostazione predefinita quando si esegue uno script, non è considerato parte di un pacchetto.

Ciò significa che per impostazione predefinita uno script può importare solo i moduli presenti nel percorso di sistema. Per impostazione predefinita, il percorso include la directory corrente, quindi se si esegue uno script, è possibile importare moduli nella stessa directory o pacchetti che sono sottodirectory. Ma è così. Uno script non ha la nozione di "dove è" nell'albero delle directory, quindi non può fare alcuna importazione che richieda informazioni sul percorso relativo specifico circa l'inclusione delle directory. Ciò significa che non puoi importare cose "dalla directory padre" o "da una directory di pari livello". Le cose che sono in quelle directory possono essere importate solo se si trovano sul percorso di sistema.

Se si desidera creare uno script "know" contenuto in un pacchetto, è possibile assegnargli un attributo __package__. Vedi this previous question. È quindi possibile utilizzare le importazioni relative esplicite (ad es., from ...sub2 import mod2) normalmente all'interno dello script.