modules from another python python-import python-module

another - python import module from path



¿Cómo hacer importaciones relativas en Python? (16)

Imagina esta estructura de directorios:

app/ __init__.py sub1/ __init__.py mod1.py sub2/ __init__.py mod2.py

Estoy codificando mod1 , y necesito importar algo desde mod2 . ¿Cómo debería hacerlo?

Intenté from ..sub2 import mod2 pero from ..sub2 import mod2 un "Intento de importación relativa en un no paquete".

Busqué en Google pero encontré solo sys.path " sys.path manipulation". ¿No hay una manera limpia?

Edición: todos mis __init__.py ''s están actualmente vacíos

Edit2: estoy intentando hacer esto porque sub2 contiene clases que se comparten entre subX ( subX , subX , etc.).

Edit3: El comportamiento que estoy buscando es el mismo que se describe en PEP 366 (gracias John B)


"Guido ve ejecutando scripts dentro de un paquete como un anti-patrón" (rechazó PEP-3122 )

He pasado mucho tiempo tratando de encontrar una solución, leyendo publicaciones relacionadas aquí en y diciéndome "¡debe haber una mejor manera!". Parece que no hay.


Además de lo que dijo John B, parece que la configuración de la variable __package__ debería ayudar, en lugar de cambiar __main__ que podría __main__ otras cosas. Pero hasta donde pude probar, no funciona completamente como debería.

Tengo el mismo problema y ninguno de los PEP 328 o 366 resuelve el problema por completo, ya que ambos, al final del día, necesitan que el responsable del paquete se incluya en sys.path , por lo que puedo entender.

También debo mencionar que no encontré cómo dar formato a la cadena que debería incluir esas variables. ¿Es "package_head.subfolder.module_name" o qué?


Aquí está la solución que funciona para mí:

from ..sub2 import mod2 relativas from ..sub2 import mod2 y luego, si quiero ejecutar mod1.py , voy al directorio principal de la app y ejecuto el módulo usando el conmutador python -m app.sub1.mod1 como python -m app.sub1.mod1 .

La verdadera razón por la que este problema ocurre con las importaciones relativas, es que las importaciones relativas funcionan tomando la propiedad __name__ 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, esa es la razón por la que Python se queja sobre la relative import in non-package error de relative import in non-package .

Por lo tanto, al usar el modificador -m, proporciona la información de la estructura del paquete a python, mediante la cual puede resolver las importaciones relativas con éxito.

He encontrado este problema muchas veces al hacer importaciones relativas. Y, después de leer todas las respuestas anteriores, todavía no pude averiguar cómo 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 de importaciones relativas, porque pasar por PEP realmente no es divertido.


Como @EvgeniSergeev dice en los comentarios al OP, puede importar código desde un archivo .py en una ubicación arbitraria con:

import imp foo = imp.load_source(''module.name'', ''/path/to/file.py'') foo.MyClass()

Esto se toma de esta respuesta SO .


Creo que lo que tienes que preguntarte es:

  • ¿Por qué necesito hacer esto?
  • ¿Está bien hecha mi separación de paquetes?

No sé el contexto por qué quieres hacerlo de esta manera. Pero para mí, un diseño más limpio sería tener la siguiente estructura de paquetes:

app/ __init__.py sub1/ __init__.py mod1.py sub12/ __init__.py mod2.py

Entonces solo tienes que hacer:

from sub12 import mod2


Desafortunadamente, este es un hack 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 el módulo 3):

mymodule/ __init__.py mymodule1/ __init__.py mymodule1_1 mymodule2/ __init__.py mymodule2_1 import mymodule.mymodule1.mymodule1_1

Tenga en cuenta que ya he instalado mymodule, pero en mi instalación no tengo "mymodule1"

y obtendría un ImportError porque estaba intentando importar desde mis módulos instalados.

Intenté hacer un sys.path.append, y eso no funcionó. Lo que funcionó fue un sys.path.insert

if __name__ == ''__main__'': sys.path.insert(0, ''../..'')

¡Qué clase de piratería, pero que todo funcionó! Entonces, tenga en cuenta que si desea que su decisión anule otras rutas, entonces debe usar sys.path.insert (0, ruta de acceso) para que funcione. Esto fue un punto de fricción muy frustrante para mí, mucha gente dice usar 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)


Descubrí que es más fácil establecer la variable de entorno "PYTHONPATH" en la carpeta superior:

bash$ export PYTHONPATH=/PATH/TO/APP

entonces:

import sub1.func1 #...more import

por supuesto, PYTHONPATH es "global", pero aún no me causó problemas.


Desde el http://docs.python.org/whatsnew/2.5.html#pep-328-absolute-and-relative-imports ,

En Python 2.5, puede cambiar el comportamiento de importación a importaciones absolutas usando una from __future__ import absolute_import . Este comportamiento de importación absoluta se convertirá en el predeterminado en una versión futura (probablemente Python 2.7). Una vez que las importaciones absolutas son el valor predeterminado, la import string siempre encontrará la versión de la biblioteca estándar. Se sugiere que los usuarios deberían comenzar a utilizar las importaciones absolutas tanto como sea posible, por lo que es preferible comenzar a escribir from pkg import string en su código.



Esto se soluciona al 100%:

  • app /
    • main.py
  • ajustes /
    • local_setings.py

Importar configuración / local_setting.py en app / main.py:

main.py:

import sys sys.path.insert(0, "../settings") try: from local_settings import * except ImportError: print(''No Import'')


Explicación de nosklo''s respuesta de nosklo''s con ejemplos.

nota: todos los archivos __init__.py están vacíos.

main.py app/ -> __init__.py package_a/ -> __init__.py fun_a.py package_b/ -> __init__.py fun_b.py

app / package_a / fun_a.py

def print_a(): print ''This is a function in dir package_a''

app / package_b / fun_b.py

from app.package_a.fun_a import print_a def print_b(): print ''This is a function in dir package_b'' print ''going to call a function in dir package_a'' print ''-''*30 print_a()

main.py

from app.package_b import fun_b fun_b.print_b()

si ejecutas $ python main.py , devuelve:

This is a function in dir package_b going to call a function in dir package_a ------------------------------ This is a function in dir package_a

  • main.py hace: from app.package_b import fun_b
  • fun_b.py hace from app.package_a.fun_a import print_a

así que el archivo en la carpeta package_b usó el archivo en la carpeta package_a , que es lo que quiere. ¿¿Derecha??


Permítanme poner esto aquí para mi propia referencia. Sé que no es un buen código de Python, pero necesitaba un script para un proyecto en el que estaba trabajando y quería colocar el script en un directorio de scripts .

import os.path import sys sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))


Supongamos que se ejecuta en el nivel superior, luego en el uso de mod1 :

import sub2.mod2

en lugar de

from ..sub2 import mod2


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 un argumento al intérprete.

Desde PEP 328 :

Las importaciones relativas utilizan el atributo __name__ de un módulo para determinar la posición de ese módulo en la jerarquía de paquetes. Si el nombre del módulo no contiene ninguna información de paquete (por ejemplo, se establece en ''__main__''), las importaciones relativas se resuelven como si el módulo fuera un módulo de nivel superior, independientemente de dónde se encuentre el módulo en el sistema de archivos.

En Python 2.6, están agregando la capacidad de referenciar módulos en relación con el módulo principal. PEP 366 describe el cambio.

Actualización : de acuerdo con Nick Coghlan, la alternativa recomendada es ejecutar el módulo dentro del paquete usando el modificador -m.


def import_path(fullpath): """ Import a file with full path specification. Allows one to import from anywhere, something __import__ does not do. """ path, filename = os.path.split(fullpath) filename, ext = os.path.splitext(filename) sys.path.append(path) module = __import__(filename) reload(module) # Might be out of date del sys.path[-1] return module

Estoy usando este fragmento para importar módulos de rutas, espero que ayude


main.py setup.py app/ -> __init__.py package_a/ -> __init__.py module_a.py package_b/ -> __init__.py module_b.py

  1. Usted ejecuta python main.py
  2. main.py hace: import app.package_a.module_a
  3. module_a.py import app.package_b.module_b

Alternativamente, 2 o 3 podrían usar: from app.package_a import module_a

Eso funcionará siempre y cuando tengas una app en tu PYTHONPATH. main.py podría estar en cualquier lugar entonces.

Entonces, escribe un setup.py para copiar (instalar) todo el paquete de aplicación y los subpaquetes a las carpetas de python del sistema de destino, y main.py a las carpetas de script del sistema de destino.