Imagine esta estructura de directorios:
app/
__init__.py
sub1/
__init__.py
mod1.py
sub2/
__init__.py
mod2.py
Estoy codificando mod1y necesito importar algo mod2. ¿Cómo debería hacerlo?
Lo intenté from ..sub2 import mod2pero obtengo un "Intento de importación relativa en un paquete no"
Busqué en Google pero encontré solo sys.pathhacks de " manipulación". ¿No hay una manera limpia?
Editar: todos mis __init__.py's están actualmente vacíos
Edit2: Estoy tratando de hacer esto porque sub2 contiene clases que se comparten a través de paquetes de sub ( sub1, subX, etc.).
Edit3: El comportamiento que estoy buscando es el mismo que se describe en PEP 366 (gracias John B)

Respuestas:
Todo el mundo parece querer decirte lo que debes hacer en lugar de solo responder la pregunta.
El problema es que está ejecutando el módulo como '__main__' pasando el mod1.py como argumento al intérprete.
Desde PEP 328 :
En Python 2.6, están agregando la capacidad de hacer referencia a módulos en relación con el módulo principal. PEP 366 describe el cambio.
Actualización : según Nick Coghlan, la alternativa recomendada es ejecutar el módulo dentro del paquete utilizando el modificador -m.
fuente
-mconmutador, en lugar de especificar su nombre de archivo directamente.from sub2 import mod2. Luego, para ejecutar mod1, desde la aplicación, hazlopython -m sub1.mod1.Aquí está la solución que funciona para mí:
Hago las importaciones relativas como
from ..sub2 import mod2y luego, si quiero ejecutar,mod1.pyentonces voy al directorio principal deappy ejecuto el módulo usando el modificador python -m comopython -m app.sub1.mod1.La verdadera razón por la cual este problema ocurre con las importaciones relativas, es que las importaciones relativas funcionan tomando la
__name__propiedad del módulo. Si el módulo se está ejecutando directamente,__name__se establece en__main__y no contiene ninguna información sobre la estructura del paquete. Y es por eso que Python se queja delrelative import in non-packageerror.Entonces, al usar el modificador -m, usted proporciona la información de la estructura del paquete a Python, a través de la cual puede resolver las importaciones relativas con éxito.
Me he encontrado con este problema muchas veces mientras hacía importaciones relativas. Y, después de leer todas las respuestas anteriores, aún no pude encontrar la manera de resolverlo, de una manera limpia, sin necesidad de poner código repetitivo en todos los archivos. (Aunque algunos de los comentarios fueron realmente útiles, gracias a @ncoghlan y @XiongChiamiov)
Espero que esto ayude a alguien que está luchando con un problema relativo de importación, porque pasar por PEP realmente no es divertido.
fuente
-mestaba diseñado para resolver.from . import some_module.python main.py.main.pyhace:import app.package_a.module_amodule_a.pyhaceimport app.package_b.module_bAlternativamente, 2 o 3 podrían usar:
from app.package_a import module_aEso funcionará mientras lo tenga
appen su PYTHONPATH.main.pypodría estar en cualquier lugar entonces.Por lo tanto, escribe un
setup.pypara copiar (instalar) el paquete completo de la aplicación y los subpaquetes en las carpetas python del sistema de destino ymain.pyen las carpetas de script del sistema de destino.fuente
"Guido ve los scripts en ejecución dentro de un paquete como un antipatrón" (rechazó PEP-3122 )
He pasado tanto tiempo tratando de encontrar una solución, leyendo publicaciones relacionadas aquí en Stack Overflow y diciéndome a mí mismo "¡debe haber una mejor manera!". Parece que no la hay.
fuente
-mswitch:python -m app.sub1.mod1o invocarapp.sub1.mod1.main()desde un script de nivel superior (por ejemplo, generado a partir de los puntos de entrada de setuptools definidos en setup.py).Esto se resuelve al 100%:
Configuración de importación / local_setting.py en app / main.py:
main.py:
fuente
sys.path.insert(0, "../settings")y luegofrom local_settings import *Estoy usando este fragmento para importar módulos desde rutas, espero que ayude
fuente
explicación de
nosklo'srespuesta con ejemplosnota: todos los
__init__.pyarchivos están vacíos.app / package_a / fun_a.py
app / package_b / fun_b.py
main.py
si lo ejecutas
$ python main.pydevuelve:from app.package_b import fun_bfrom app.package_a.fun_a import print_aasí que el archivo en la carpeta
package_butiliza el archivo en la carpetapackage_a, que es lo que quieres. ¿¿Derecha??fuente
Desafortunadamente, este es un truco de sys.path, pero funciona bastante bien.
Encontré este problema con otra capa: ya tenía un módulo con el nombre especificado, pero era el módulo incorrecto.
lo que quería hacer era lo siguiente (el módulo desde el que estaba trabajando era module3):
Tenga en cuenta que ya instalé mymodule, pero en mi instalación no tengo "mymodule1"
y obtendría un ImportError porque intentaba importar desde mis módulos instalados.
Traté de hacer un sys.path.append, y eso no funcionó. Lo que funcionó fue un sys.path.insert
Fue un truco, ¡pero todo funcionó! Por lo tanto, tenga en cuenta que si desea que su decisión anule otras rutas , ¡debe usar sys.path.insert (0, pathname) para que funcione! Este fue un punto muy frustrante para mí, mucha gente dice que use la función "agregar" a sys.path, pero eso no funciona si ya tiene un módulo definido (me parece un comportamiento muy extraño)
fuente
sys.path.append('../')funciona bien para mí (Python 3.5.2)Permítanme poner esto aquí para mi propia referencia. Sé que no es un buen código Python, pero necesitaba un script para un proyecto en el que estaba trabajando y quería colocar el script en un
scriptsdirectorio.fuente
Como @EvgeniSergeev dice en los comentarios al OP, puede importar código de un
.pyarchivo en una ubicación arbitraria con:Esto se toma de esta respuesta SO .
fuente
Eche un vistazo a http://docs.python.org/whatsnew/2.5.html#pep-328-absolute-and-relative-imports . Podrías hacerlo
fuente
De Python doc ,
fuente
Descubrí que es más fácil establecer la variable de entorno "PYTHONPATH" en la carpeta superior:
entonces:
por supuesto, PYTHONPATH es "global", pero todavía no me planteó problemas.
fuente
virtualenvpermite administrar sus declaraciones de importación.Además de lo que dijo John B, parece que establecer la
__package__variable debería ayudar, en lugar de cambiar lo__main__que podría arruinar otras cosas. Pero por lo que pude probar, no funciona completamente como debería.Tengo el mismo problema y ni PEP 328 ni 366 resuelven el problema por completo, ya que ambos, al final del día, necesitan que se incluya el encabezado del paquete en
sys.path, por lo que pude entender.También debo mencionar que no encontré cómo formatear la cadena que debería ir a esas variables. ¿Es
"package_head.subfolder.module_name"o qué?fuente
Debe agregar la ruta del módulo a
PYTHONPATH:fuente
sys.path, ya quesys.pathse inicializa desdePYTHONPATHsys.pathnecesita ser codificado en el código fuente en contraste con loPYTHONPATHque es una variable de entorno y se puede exportar.