2011-08-25 8 views
5

Ho due progetti separati che condividono il nome di un pacchetto. Funzionano correttamente purché non siano entrambi su PYTHONPATH, ma non appena entrambi appaiono, uno di loro non riesce a trovare le importazioni nel proprio progetto.I moduli con una gerarchia di pacchetti comune menzionati più volte nel mio PYTHONPATH?

esempio, due progetti come questo:

Progetto 1:

x/ 
    __init__.py 
    test.py 
    foo.py 

test.py contiene la riga:

import x.foo 

Progetto 2:

x/ 
    __init__.py 
    bar.py 

Se Corro

PYTHONPATH=. python x/y/test.py 

non ci sono errori. Ma se corro

PYTHONPATH='pathtoproject2:.' python x/test.py 

ottengo l'errore:

Traceback (most recent call last): 
    File "x/test.py", line 1, in <module> 
    import x.foo 
ImportError: No module named foo 

C'è un modo per avere diversi progetti Python con una quota pacchetto comune la PYTHONPATH? O Python utilizzerà sempre solo il primo percorso in cui viene trovato un pacchetto?

Nota: so se si modifica l'importazione da x.foo per importare foo, quindi funzionerà. Ma voglio sapere se è possibile farlo senza modificare alcun pacchetto.

risposta

3

Attualmente, Python non supporta pacchetti da diverse directory. Un pacchetto è un'unità, non solo uno spazio dei nomi. Questo è diverso dai "pacchetti" di Java o dagli "spazi dei nomi" più appropriatamente definiti in .NET.

Quando si importa un pacchetto, Python eseguirà la scansione sys.path, in sequenza, e utilizzerà la prima corrispondenza. Se c'è un altro modulo o pacchetto con un nome corrispondente in una directory che appare più avanti nel percorso, non verrà trovato.

La tua "nota" non è vera, a proposito. Quando si utilizza import foo, Python proverà un'importazione relativa all'interno della directory di test.py, non trova corrispondenza, quindi tenta un'importazione assoluta del modulo foo, che non esiste neanche e quindi genera un valore ImportError.

Invece di utilizzare i nomi dei pacchetti per raggruppare i moduli utilizzando un prefisso comune, si pensi ai pacchetti come librerie autonome di dimensioni ridotte. In Python, flat is better than nested, ed è preferibile avere più pacchetti di primo livello, ciascuno che soddisfa uno scopo distinto, che avere un unico pacchetto monolitico. Invece di org.example.foo e org.example.bar, utilizzare solo foo e bar.

+0

+1 sembra che anche se possibile, come spiegato nel altra risposta, non è il modo in cui Python .. . –

2

Sebbene non supportato in modo nativo dal meccanismo di importazione, esiste una soluzione alternativa per creare pacchetti con nomi in python. Devi solo inserire il seguente codice su entrambi i file __init__.py.

try: 
    import pkg_resources 
    pkg_resources.declare_namespace(__name__) 
except ImportError: 
    import pkgutil 
    __path__ = pkgutil.extend_path(__path__, __name__) 

pkg_resources è fornita da setuptools pacchetto python e ha il vantaggio che gestisce anche i pacchetti contenuti nei file zip uovo.

pkgutil è contenuta nella libreria standard di Python così contiamo su di esso per gestire l'estensione dello spazio dei nomi, se setuptools non è installato nel sistema.

per ulteriori informazioni sui pacchetti namespace Python può essere trovato qui:

http://packages.python.org/distribute/setuptools.html#namespace-packages

http://www.python.org/dev/peps/pep-0382/

Problemi correlati