librerias - lista de modulos de python
¿Cómo utilizar correctamente las importaciones relativas o absolutas en los módulos de Python? (6)
Podrías simplemente comenzar a ''ejecutar los módulos como standalones'' de una forma un poco diferente:
En lugar de:
python foo/bar.py
Utilizar:
python -mfoo.bar
Por supuesto, el archivo foo/__init__.py
debe estar presente.
Tenga en cuenta también que tiene una dependencia circular entre foo.py
y bar.py
; esto no funcionará. Supongo que es solo un error en tu ejemplo.
Actualización: parece que también funciona perfectamente para usar esto como la primera línea de foo/bar.py
:
#!/usr/bin/python -mfoo.bar
Luego puede ejecutar el script directamente en sistemas POSIX.
El uso de importaciones relativas en Python tiene un inconveniente, ya no podrá ejecutar los módulos como standalones porque obtendrá una excepción: ValueError: Attempted relative import in non-package
# /test.py: just a sample file importing foo module
import foo
...
# /foo/foo.py:
from . import bar
...
if __name__ == "__main__":
pass
# /foo/bar.py: a submodule of foo, used by foo.py
from . import foo
...
if __name__ == "__main__":
pass
¿Cómo debo modificar el código de muestra para poder ejecutar todo: test.py
, foo.py
y bar.py
Estoy buscando una solución que funcione con Python 2.6+ (incluyendo 3.x).
¿Por qué no simplemente poner el "principal" en un archivo .py diferente?
Hasta ahora, la única solución que encontré fue no utilizar importaciones relativas en absoluto.
Debido a la limitación actual, me pregunto cuándo se supone que alguien debe usar importaciones relativas en python.
En todas las configuraciones que utilicé, sys.path
contenía el directorio actual como primer argumento, así que use import foo
lugar de from . import foo
from . import foo
porque hará lo mismo.
Importaciones relativas de zanjas: de todos modos, debería pensar en el espacio de nombres de su paquete como global.
El truco para hacer que esto sea aceptable es editar sys.path
apropiada. He aquí algunos elementos de reflexión:
# one directory up _root_dir = os.path.dirname(os.path.dirname(os.path.realpath(__file__))) sys.path.insert(0, _root_dir)for now
Necesitas __init__.py
en cada carpeta.
La importación relativa funciona solo cuando lo haces:
python test.py
las importaciones de test.py foo.py y foo.py pueden importar cualquier cosa desde la carpeta de test.py y superior.
No puedes hacer:
cd foo
python foo.py
python bar.py
Nunca funcionará.
Puedes probar la solución sys.path.append o sys.path.insert pero vas a arruinar las rutas y tendrás problemas con f = open (filename).
En primer lugar, supongo que se da cuenta de que lo que ha escrito conduciría a un problema de importación circular, porque foo importa la barra y viceversa; intente agregar
from foo import bar
a test.py, y verá que falla. El ejemplo debe ser cambiado para poder funcionar.
Entonces, lo que está pidiendo es realmente retroceder a la importación absoluta cuando falla la importación relativa; de hecho, si está ejecutando foo.py o bar.py como el módulo principal, los demás módulos se encontrarán en el nivel raíz, y si comparten el nombre con otro módulo del sistema, el que se seleccionará depende de el orden en sys.path. Dado que el directorio actual es generalmente el primero, los módulos locales se seleccionarán si están disponibles; es decir, si tiene un archivo ''os.py'' en el directorio de trabajo actual, se seleccionará en lugar de uno integrado.
Una sugerencia posible es:
foo.py
try:
from . import bar
except ValueError:
import bar
if __name__ == "__main__":
pass
bar.py:
if __name__ == "__main__":
pass
Por cierto, llamar a los scripts desde la posición correcta suele ser mucho mejor.
python -m foo.bar
Es probablemente la mejor manera de ir. Esto ejecuta el módulo como un script .