2015-11-23 7 views
16

Ho un progetto pitone (che ho eseguito all'interno di un virtualenv) e che ha la seguente struttura:Python non riesce a trovare il mio modulo

Project 
├───.git 
├───venv 
└───src 
    ├───__init__.py 
    ├───mymodules 
    │ ├───__init__.py 
    │ ├───module1.py 
    │ └───module2.py 
    └───scripts 
     ├───__init__.py 
     └───script.py 

script.py

import src.mymodules.module1 
... 

Eseguo il progetto con venv attivato e dalla directory Progetto utilizzando il seguente comando:

(venv)$ python src/scripts/script.py 

Lo script viene eseguito, ma dà il seguente errore prima di uscire:

Traceback (most recent call last): 
    File "src/scripts/script.py", line 1, in <module> 
    import src.mymodules.module1 
ImportError: No module named src.mymodules.module1 

Ho provato a fare funzionare il guscio pitone e cercando di importare il modulo da lì e ha dato nessun errore. Ho _ _init__.py in ogni directory all'interno di src. Python considera la directory di lavoro come src/scripts? Perché sta succedendo e come posso creare src la directory di lavoro, se è così?

+0

Python 2 o 3? 3 ha un modo diverso di gestire le importazioni dei moduli del pacchetto. – Mego

+0

@Mego Python 2.7 – CrazyJony

+0

Questo potrebbe aiutare http://stackoverflow.com/questions/33773202/how-to-import-a-class-from-a-different-folder-in-python/33773635#33773635 –

risposta

10

In sostanza, quando si esegue direttamente script.py, non si sa che fa parte di un sottomodulo di src, né sa dove potrebbe trovarsi un modulo denominato src. Questo è il caso in python 2 o 3.

Come sapete, Python trova moduli basati sul contenuto di sys.path. Per importare qualsiasi modulo, è necessario trovarlo in una directory elencata in sys.path o nella stessa directory dello script in esecuzione.

Quando si dice python src/scripts/script.py, sys.path include il Project/src/scripts/ (perché è lì che si trova script.py), ma non Project. Poiché Project non si trova nel percorso, i moduli in tale directory (src) non possono essere importati.

Per fissare questo:

sto supponendo che il vostro script.py è un punto di ingresso per il modulo src (ad esempio, forse è il programma principale). Se questo è vero, allora si potrebbe risolvere il problema spostando script.py fino allo stesso livello come src:

Project 
├───.git 
├───venv 
|───script.py  <--- script.py moves up here 
└───src 
    ├───__init__.py 
    └───mymodules 
     ├───__init__.py 
     ├───module1.py 
     └───module2.py 

In questo modo, script.py possono liberamente importare nulla in src, ma nulla in src possibile importare script.py.

Se questo non è il caso, e script.py è davvero una parte di src, è possibile utilizzare l'argomento di pitone -m di eseguire script.py come parte del src modulo in questo modo: pitone

$ python -m src.scripts.script 

Perché tu hai detto quale modulo stai utilizzando (src), sarà nel percorso. Quindi, script.py saprà che è un sottomodulo di src, e quindi sarà in grado di importare da src.

Attenzione però in questa situazione: è possibile creare un'importazione circolare se qualcosa in src importa src.scripts.script.


In alternativa a questi due approcci, è possibile modificare la sys.path direttamente in script.py:

import sys 
sys.path.insert(0, '/path/to/Project') # location of src 

Anche se questo funziona, di solito non è la mia preferenza. Richiede script.py per sapere esattamente come è disposto il codice e può causare confusione nell'importazione se un altro programma python tenta di importare script.py.

+0

Grazie, tutte e 3 le opzioni funzionano. Il primo non è un'opzione per questo progetto. Il terzo non è molto elegante per la ragione che hai affermato. Per ora, penso che userò 'python -m src.scripts.script'. Ho pensato che sarebbe stato sufficiente strutturarlo come un pacchetto, come ho visto in altre domande qui? – CrazyJony

+0

Python non va su "su" livelli di directory per trovare pacchetti per vari motivi. E i sottomoduli possono e devono importare fratelli, ma per lo più i pacchetti sono pensati per essere usati da altri programmi (e installati in una directory del pacchetto di sistema), non necessariamente per essere programmi in se stessi. Questa parte di Python può essere confusa, ma ha un senso. – Seth

0
Project 
├───.git 
├───venv 
└───src 
    ├───__init__.py 
    ├───mymodules 
    │ ├───__init__.py 
    │ ├───module1.py 
    │ └───module2.py 
    └───scripts 
     ├───__init__.py 
     └───script.py 

In alternativa è possibile importare come il seguente nella vostra script.py

import os 
import sys 
sys.path.append(os.path.join(os.path.dirname(__file__),'../../')) 
import src.mymodules.module1 

Ora è possibile eseguire il file script.py da qualsiasi posizione.

e.g : 
python script.py 
python /path to folder/script.py