Imagine esta estructura de directorios:
app/
__init__.py
sub1/
__init__.py
mod1.py
sub2/
__init__.py
mod2.py
Estoy codificando mod1
y necesito importar algo mod2
. ¿Cómo debería hacerlo?
Lo intenté from ..sub2 import mod2
pero obtengo un "Intento de importación relativa en un paquete no"
Busqué en Google pero encontré solo sys.path
hacks 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
-m
conmutador, 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 mod2
y luego, si quiero ejecutar,mod1.py
entonces voy al directorio principal deapp
y 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-package
error.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
-m
estaba diseñado para resolver.from . import some_module
.python main.py
.main.py
hace:import app.package_a.module_a
module_a.py
haceimport app.package_b.module_b
Alternativamente, 2 o 3 podrían usar:
from app.package_a import module_a
Eso funcionará mientras lo tenga
app
en su PYTHONPATH.main.py
podría estar en cualquier lugar entonces.Por lo tanto, escribe un
setup.py
para copiar (instalar) el paquete completo de la aplicación y los subpaquetes en las carpetas python del sistema de destino ymain.py
en 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
-m
switch:python -m app.sub1.mod1
o 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's
respuesta con ejemplosnota: todos los
__init__.py
archivos están vacíos.app / package_a / fun_a.py
app / package_b / fun_b.py
main.py
si lo ejecutas
$ python main.py
devuelve:from app.package_b import fun_b
from app.package_a.fun_a import print_a
así que el archivo en la carpeta
package_b
utiliza 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
scripts
directorio.fuente
Como @EvgeniSergeev dice en los comentarios al OP, puede importar código de un
.py
archivo 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
virtualenv
permite 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.path
se inicializa desdePYTHONPATH
sys.path
necesita ser codificado en el código fuente en contraste con loPYTHONPATH
que es una variable de entorno y se puede exportar.