Estoy desarrollando varios proyectos de Python para varios clientes al mismo tiempo. Una versión simplificada de la estructura de mi carpeta de proyecto se ve algo como esto:ruta de importación python: paquetes con el mismo nombre en diferentes carpetas
/path/
to/
projects/
cust1/
proj1/
pack1/
__init__.py
mod1.py
proj2/
pack2/
__init__.py
mod2.py
cust2/
proj3/
pack3/
__init__.py
mod3.py
Cuando, por ejemplo, desea utilizar la funcionalidad de proj1
, que se extienden sys.path
por /path/to/projects/cust1/proj1
(por ejemplo, fijando PYTHONPATH
o añadir un archivo .pth
a la carpeta site_packages
o incluso modificar sys.path
directamente) y luego importar el módulo de la siguiente manera:
>>> from pack1.mod1 import something
como yo trabajo en más proyectos, ocurre que diferentes proyectos tienen nombres de paquetes idénticos:
/path/
to/
projects/
cust3/
proj4/
pack1/ <-- same package name as in cust1/proj1 above
__init__.py
mod4.py
Si ahora simplemente extiendo sys.path
por /path/to/projects/cust3/proj4
, todavía puedo importar de proj1
, pero no de proj4
:
>>> from pack1.mod1 import something
>>> from pack1.mod4 import something_else
ImportError: No module named mod4
Creo que la razón por la cual la segunda importación falla es que Python sólo se busca en el primera carpeta en sys.path
donde encuentra un paquete pack1
y se da por vencido si no encuentra allí el módulo mod4
. He preguntado sobre esto en una pregunta anterior, vea import python modules with the same name, pero los detalles internos aún no están claros para mí.
De todos modos, la solución obvia es agregar otra capa de cualificación espacio de nombres girando directorios de proyectos en paquetes súper: Añadir __init__.py
archivos en cada carpeta proj*
y eliminar estas carpetas desde las líneas por el que se amplía, por ejemplo sys.path
$ export PYTHONPATH=/path/to/projects/cust1:/path/to/projects/cust3
$ touch /path/to/projects/cust1/proj1/__init__.py
$ touch /path/to/projects/cust3/proj4/__init__.py
$ python
>>> from proj1.pack1.mod1 import something
>>> from proj4.pack1.mod4 import something_else
Ahora estoy corriendo en una situación en diferentes proyectos para diferentes clientes tienen el mismo nombre, por ejemplo,
/path/
to/
projects/
cust3/
proj1/ <-- same project name as for cust1 above
__init__.py
pack4/
__init__.py
mod4.py
Tratando de importar de mod4
ya no funciona por la misma razón que antes:
>>> from proj1.pack4.mod4 import yet_something_else
ImportError: No module named pack4.mod4
Siguiendo el mismo enfoque que resuelve este problema antes, me gustaría añadir otra capa de paquete/espacio de nombres y convierta las carpetas de los clientes en súper súper paquetes.
Sin embargo, esto choca con otros requisitos que tengo con la estructura de mi carpeta de proyecto, p.
- Desarrollo estructura/Liberación de mantener varias líneas de código
- otros tipos de código fuente, como por ejemplo, JavaScript, SQL, etc.
- otros archivos que no sean archivos de origen, como p. Ej. documentos o datos
A menos simplificada, más la representación del mundo real de algunas carpetas del proyecto es el siguiente:
/path/
to/
projects/
cust1/
proj1/
Development/
code/
javascript/
...
python/
pack1/
__init__.py
mod1.py
doc/
...
Release/
...
proj2/
Development/
code/
python/
pack2/
__init__.py
mod2.py
no veo cómo puedo satisfacer las necesidades del intérprete Python tiene una estructura de carpetas y los que tengo al mismo tiempo. Tal vez podría crear una estructura de carpetas adicional con algunos enlaces simbólicos y usar eso en sys.path
, pero mirando el esfuerzo que ya estoy haciendo, tengo la sensación de que hay algo fundamentalmente erróneo en todo mi enfoque. En una nota al margen, también me cuesta creer que Python realmente me restringe en mi elección de los nombres de las carpetas del código fuente, como parece hacer en el caso que se muestra.
¿Cómo puedo configurar mis carpetas de proyecto y sys.path
para que pueda importar de todos los proyectos de manera consistente si hay proyectos y paquetes con nombres idénticos?
Los estoy usando, pero solo proporcionan una solución siempre que importe entre proyectos del mismo cliente. Si necesito importar desde un ámbito más amplio, surge el mismo conflicto en un entorno virtual en el sistema python env. Además, tanto como me gusta virtualenv, desde mi punto de vista, revisa una deficiencia importante del intérprete de Python. ¿Soy realmente el único que se encuentra con este problema? – ssc
En mi humilde opinión, no debería compartir la funcionalidad entre los proyectos de esa manera. Si necesitan compartir alguna implementación, considere extraerla como biblioteca e incluirla en ambos proyectos – zsquare
hmmm, entonces pregunto cómo hacer algo y la respuesta es no hacerlo?!? eso no es lo que esperaba. casualmente, en realidad estoy haciendo lo que sugiere: extraigo la funcionalidad en una biblioteca y la uso en otros proyectos, que es exactamente donde surge este problema de ruta de importación. Me da la impresión de que este es un problema que todos los demás simplemente trabajan de alguna manera y tendré que aceptar esta restricción de importación y, p. introduzca una convención para importar solo entre paquetes del mismo cliente (y también mantener un entorno virtual por cliente). – ssc