2013-08-30 17 views
9

Ho un programma python che è interamente contenuto in una directory con la seguente struttura:Python: moduli e packaging: perché il file __init__.py non è eseguito prima di __main__.py?

myprog/ 
├── __init__.py 
├── __main__.py 
├── moduleone.py 
└── moduletwo.py 

Vorrei essere in grado di confezionare questo e distribuirlo in modo che un altro sviluppatore può fare pip install -e /path/to/git/clone/of/myprog e possono quindi importare myprog nei suoi programmi e fare cose interessanti con esso.

Vorrei anche essere in grado di eseguire myprog nella riga di comando come segue:

PROMPT> python myprog 

Quando faccio questo, mi aspetto di pitone per eseguire il modulo __main__.py, cosa che fa. Tuttavia, questo modulo fa riferimento ad alcune funzioni dichiarate in __init__.py e che devono essere disponibili sia quando il programma viene eseguito sulla riga di comando sia quando viene importato da un altro programma. Tuttavia, sto ottenendo il seguente errore:

NameError: name 'function_you_referenced_from_init_file' is not defined 

Devo importare queste funzioni in __main__.py in qualche modo?

Ho provato un semplice esempio come segue:

PROMPT> cat myprog/__init__.py 
def init_myprog(): 
    print 'running __init__.init_myprog()' 

PROMPT> cat myprog/__main__.py 
import myprog 
print 'hi from __main__.py' 
myprog.init_myprog() 

PROMPT> ls -l myprog 
total 16 
-rw-r--r-- 1 iit 63B Aug 30 11:40 __init__.py 
-rw-r--r-- 1 iit 64B Aug 30 12:11 __main__.py 

PROMPT> python myprog 
Traceback (most recent call last): 
    File "/usr/local/Cellar/python/2.7.5/Frameworks/Python.framework/Versions/2.7/lib/python2.7/runpy.py", line 162, in _run_module_as_main 
    "__main__", fname, loader, pkg_name) 
    File "/usr/local/Cellar/python/2.7.5/Frameworks/Python.framework/Versions/2.7/lib/python2.7/runpy.py", line 72, in _run_code 
    exec code in run_globals 
    File "/Users/jon/dev/myprog/__main__.py", line 1, in <module> 
    import myprog 
ImportError: No module named myprog 
+2

A chi sta votando per chiudere la domanda - se è così stupido e semplice, forse potresti spiegarmelo in un paio di secondi? Ho cercato di imparare da questo link http://stackoverflow.com/questions/3411293/using-modules-own-objects-in-main-py ma ho ancora problemi. – jononomo

+0

Devi importare tutto tranne i builtin, quindi la risposta è un "sì" piuttosto ovvio. –

risposta

9

Do I have to import these functions into __main__ somehow?

Sì. Solo gli articoli in builtins sono disponibili senza importazione. Qualcosa di simile:

from myprog import func1, func2 

dovrebbe fare il trucco.

Se non si dispone di myprog installato nel normale percorso di python allora si può lavorare intorno ad esso con qualcosa di simile:

import sys 
import os 
path = os.path.dirname(sys.modules[__name__].__file__) 
path = os.path.join(path, '..') 
sys.path.insert(0, path) 
from myprog import function_you_referenced_from_init_file 

che, francamente, è orrendo.

io vi suggerisco di andare con MartijnPieters suggestion e mettere il -m sulla riga di comando, nel qual caso __main__.py può sembrare:

from myprog import function_you_referenced_from_init_file 
+0

Sembra ottimo, ma non funziona sulla mia macchina. Ho provato due o tre diverse varianti di importazione e ottengo sempre "ImportError: No module named myprog" – jononomo

+0

Vedere la mia modifica al post originale per ulteriori dettagli. – jononomo

+0

@JonCrowell: Quindi non hai il modulo myprog installato, quindi Python non lo trova. Guarda il packaging e lo sviluppo: http://guide.python-distribute.org/ http://www.scotttorborg.com/python-packaging/ Quick hack: aggiungi la directory sopra myprog a PYTHOPATH. –

13

Il __init__.py viene caricato solo quando si è importare il pacchetto. Stai invece trattando la directory come uno script, eseguendo la directory.

È tuttavia possibile considerare il pacchetto come uno script, invece della directory. Per entrambe trattano la directory come un pacchetto e dello script principale, utilizzando l'interruttore -m:

python -m myprog 
+0

L'ho provato e ora ho ricevuto un 'modulo No myprog'. [Questa risposta] (http://stackoverflow.com/questions/16637428/relative-import-in-python-3-not-working#33195094) sembra indicare che trattare una directory come un pacchetto * e * uno script sono cattivi pratica. Pensieri? – Jens

+0

La risposta afferma un'opinione personale. Diversi moduli di libreria standard, oltre a pacchetti popolari come 'virtualenv' e il supporto' pip' vengono eseguiti come script. Personalmente apprezzo e utilizzo questa funzionalità. Se stai ricevendo un errore * Nessun modulo chiamato Foo *, il tuo modulo non può essere importato neanche; sei sicuro che sia disponibile sul tuo percorso Python? –

2

Così, dopo aver guardato le altre risposte e non restare ammaliati, ho provato:

from __init__ import * 

dal mio file __main__.py.

Suppongo che non ti consenta di fare riferimento al modulo per nome, ma per casi semplici sembra funzionare.

Problemi correlati