python - framework - tutorial django
La respuesta definitiva a las importaciones relativas de Python (2)
Eche un vistazo a la siguiente información de PEP 328 :
Las importaciones relativas usan el atributo
__name__
un módulo para determinar la posición de ese módulo en la jerarquía del paquete. Si el nombre del módulo no contiene ninguna información del paquete (p. Ej., Está establecido en''__main__''
), las importaciones relativas se resuelven como si el módulo fuera un módulo de nivel superior, independientemente de dónde esté realmente ubicado el módulo en el sistema de archivos.
Cuando ejecuta foo.py
como script, el __name__
ese módulo es ''__main__''
, por lo que no puede hacer importaciones relativas. Esto sería cierto incluso si mi mypackage
estaba en sys.path
. Básicamente, solo puede hacer importaciones relativas desde un módulo si ese módulo se importó.
Aquí hay algunas opciones para solucionar esto:
1) En foo.py
, compruebe si __name__ == ''__main__''
y agregue condicionalmente mypackage
a sys.path
:
if __name__ == ''__main__'':
import os, sys
# get an absolute path to the directory that contains mypackage
foo_dir = os.path.dirname(os.path.join(os.getcwd(), __file__))
sys.path.append(os.path.normpath(os.path.join(foo_dir, ''..'', ''..'')))
from mypackage import bar
else:
from .. import bar
2) from mypackage import bar
siempre la bar
from mypackage import bar
y ejecute foo.py
de tal forma que mypackage
sea visible automáticamente:
$ cd <path containing mypackage>
$ python -m mypackage.foo.foo
Sé que hay muchas preguntas sobre los mismos problemas de importación en Python, pero parece que nadie logró dar un ejemplo claro del uso correcto.
Digamos que tenemos un paquete mypackage
con dos módulos foo
y bar
. Dentro de foo
tenemos que poder acceder a la bar
.
Como todavía estamos desarrollándolo, mypackage
no está en sys.path
.
Queremos ser capaces de:
- importar
mypackage.foo
- ejecute
foo.py
como un script y ejecute el uso de muestra o las pruebas de la sección__main__
. - usa Python 2.5
¿Cómo tenemos que hacer la importación en foo.py para estar seguros de que funcionará en todos estos casos?
# mypackage/__init__.py
...
# mypackage/foo/__init__.py
...
# mypackage/bar.py
def doBar()
print("doBar")
# mypackage/foo/foo.py
import bar # fails with module not found
import .bar #fails due to ValueError: Attempted relative import in non-package
def doFoo():
print(doBar())
if __name__ == ''__main__'':
doFoo()
Mi solución parece un poco más limpia y puede ir en la parte superior, con todas las demás importaciones:
try:
from foo import FooClass
except ModuleNotFoundError:
from .foo import FooClass