¿Cómo funcionan las importaciones relativas implícitas en Python?

Supongamos que tengo los siguientes archivos,

pkg/ pkg/__init__.py pkg/main.py # import string pkg/string.py # print("Package's string module imported") 

Ahora, si ejecuto main.py , dice "Package's string module imported" .

Esto tiene sentido y funciona según esta statement en este enlace :

“Primero mirará en el directorio del paquete”

Supongamos que modifiqué ligeramente la estructura de archivos (agregue un directorio central)

 pkg/ pkg/__init__.py plg/core/__init__.py pkg/core/main.py # import string pkg/string.py # print("Package's string module imported") 

Ahora, si ejecuto python core/main.py , se carga el módulo de string incorporado.

También en el segundo caso, si tiene que cumplir con la statement ” primero buscará en el directorio del paquete” ¿no debería cargar el string.py local porque pkg es el “directorio del paquete”?

Mi sentido del término “directorio de paquetes” es específicamente la carpeta raíz de una colección de carpetas con __init__.py . Entonces, en este caso, pkg es el “directorio de paquetes”. Es aplicable a main.py y también a archivos en subdirectorios como core/main.py porque forma parte de este “paquete”.

¿Es esto técnicamente correcto?

PD: Lo que sigue después de # en el fragmento de código es el contenido real del archivo (sin espacios iniciales).

Related of "¿Cómo funcionan las importaciones relativas implícitas en Python?"

Los paquetes son directorios con un archivo __init__.py , sí, y se cargan como un módulo cuando se encuentran en la ruta de búsqueda del módulo . Por lo tanto, pkg es solo un paquete que puede importar y tratar como un paquete si el directorio principal está en la ruta de búsqueda del módulo .

Pero al ejecutar el archivo pkg/core/main.py como una secuencia de comandos , Python agregó el directorio pkg/core a la ruta de búsqueda del módulo, no al directorio principal de pkg . __init__.py tiene un archivo __init__.py en la ruta de búsqueda de su módulo, pero eso no es lo que define un paquete. Simplemente tiene un módulo __main__ , no hay relación de paquete con ninguna otra cosa y no puede confiar en las importaciones relativas implícitas.

Tienes tres opciones:

  1. No ejecute archivos dentro de paquetes como scripts. Coloque un archivo de script fuera de su paquete y haga que importe su paquete según sea necesario. Puede colocarlo junto al directorio pkg , o asegurarse de que el directorio pkg se instale por primera vez en un directorio que ya se encuentra en la ruta de búsqueda del módulo, o que su script calcule la ruta correcta para agregar a sys.path .

  2. Utilice el -m línea de comando -m para ejecutar un módulo como si fuera un script. Si usa python -m pkg.core Python buscará un archivo __main__.py y lo ejecutará como un script. El -m agregará el directorio de trabajo actual a la ruta de búsqueda del módulo, por lo que puede usar ese comando cuando esté en el directorio de trabajo correcto y todo funcionará. O tenga su paquete instalado en un directorio que ya se encuentra en la ruta de búsqueda del módulo.

  3. Haga que su script agregue el directorio correcto a la ruta de búsqueda del módulo (basado en os.path.absolute(__file__) para obtener una ruta al archivo actual). Tenga en cuenta que su script siempre se llama __main__ , y la importación de pkg.core.main agregaría un segundo objeto de módulo independiente; Tendrías dos espacios de nombres separados.

También aconsejo firmemente no usar las importaciones relativas implícitas. Puede enmascarar fácilmente módulos y paquetes de nivel superior agregando un paquete o módulo nested con el mismo nombre. pkg/time.py se encontraría antes del módulo de time biblioteca estándar si intentara usar el import time dentro del paquete pkg . En su lugar, use el modelo de Python 3 de referencias explícitas relativas a módulos; agregue from __future__ import absolute_import a todos sus archivos, y luego use from . import from . import para ser explícito en cuanto a desde dónde se importa su módulo.