2011-08-25 10 views
5

Tengo dos proyectos separados que comparten un nombre de paquete. Funcionan bien siempre que no estén ambos en PYTHONPATH, pero tan pronto como aparezcan, uno de ellos no puede encontrar importaciones en su propio proyecto.¿Pueden los módulos con una jerarquía de paquete común mencionar varias veces en mi PYTHONPATH?

ejemplo, dos proyectos como este:

Proyecto 1:

x/ 
    __init__.py 
    test.py 
    foo.py 

test.py contiene la línea:

import x.foo 

Proyecto 2:

x/ 
    __init__.py 
    bar.py 

Si Corro

PYTHONPATH=. python x/y/test.py 

no hay ningún error. Pero si me quedo

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

me sale el error:

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

¿Hay una manera de tener diferentes proyectos Python con una cuota de paquete común del PYTHONPATH? ¿O Python siempre usará solo la primera ruta donde se encuentra un paquete?

Nota: Sé que si modifica la importación de x.foo importar foo entonces todo funcionará bien. Pero quiero saber si es posible hacerlo sin modificar ninguno de los paquetes.

Respuesta

3

Actualmente, Python no admite paquetes de directorios diferentes. Un paquete es una unidad, no solo un espacio de nombres. Esto es diferente de los "paquetes" de Java o los "espacios de nombres" más apropiadamente nombrados en .NET.

Al importar un paquete, Python escanear sys.path, de forma secuencial, y utilizar el primer partido. Si hay otro módulo o paquete con un nombre coincidente en un directorio que aparece más adelante en la ruta, no se encontrará.

su "nota" no es cierto, por cierto. Cuando se utiliza import foo, Python intentará una importación relativa dentro del directorio de test.py, encontrar ninguna coincidencia, a continuación, intentar una importación absoluto del módulo de foo, que no existe tampoco, y luego levantar una ImportError.

En lugar de utilizar nombres de paquetes de módulos de grupo utilizando un prefijo común, pensar en paquetes como bibliotecas más bien pequeñas, independientes. En Python, flat is better than nested, y es preferible tener múltiples paquetes de nivel superior, cada uno cumpliendo un propósito distinto, que tener un paquete monolítico grande. En lugar de org.example.foo y org.example.bar, simplemente use foo y bar.

+0

+1 Parece que, aunque es posible, como se explica en la otra respuesta, no es la forma en Python .. . –

2

Aunque no es compatible de forma nativa por el mecanismo de importación, no es una solución solución para crear paquetes de espacios de nombres en Python. Solo tiene que poner el siguiente código en ambos archivos __init__.py.

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

pkg_resources es proporcionada por setuptools paquete python y tiene la ventaja de que también se ocupa de los paquetes contenidos en archivos zip huevo.

pkgutil está contenido en la biblioteca estándar de python, por lo que confiamos en él para manejar la extensión del espacio de nombres si setuptools no está instalado en el sistema.

para obtener más información acerca de los paquetes de espacio de nombres de Python se puede encontrar aquí:

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

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

Cuestiones relacionadas