modules - python packages
¿Por qué "importar módulo" y luego "desde paquete módulo de importación" cargar el módulo de nuevo? (2)
Tengo un paquete en mi PYTHONPATH que se ve así:
package/
__init__.py
module.py
print ''Loading module''
Si estoy ejecutando Python desde el package/
directorio (o escribiendo otro módulo en este directorio) y escribo
import module
carga module.py e imprime "Cargando el módulo" como se esperaba. Sin embargo, si luego escribo
from package import module
carga module.py e imprime "Cargando módulo" nuevamente , lo que no espero. ¿Cuál es la razón de esto?
Nota: Creo que entiendo técnicamente por qué Python está haciendo esto, porque la clave sys.modules para el import module
es solo "module"
, pero para el from package import module
es "package.module"
. Así que supongo que lo que quiero saber es por qué la clave es diferente aquí. ¿Por qué no se usa la clave del archivo como clave para que Python haga lo que se espera aquí?
Efectivamente, al ejecutar código desde el directorio del package
, ha configurado incorrectamente Python. No debería haber puesto ese directorio en sys.path
, ya que está dentro de un paquete.
Python no usa el nombre de archivo como la clave porque no está importando un archivo, sino que está importando un módulo. Permitir que la gente haga '' import c:/jim/my files/projects/code/stuff
'' alentaría todo tipo de maldad.
Considere este caso en su lugar: ¿y si estuvieras en ~/foo/package/
y ~/bar
estuviera en PYTHONPATH
- pero ~ / bar es solo un enlace simbólico a ~/foo
? ¿Esperas que Python se resuelva, luego deduplicas el enlace simbólico por ti? ¿Qué sucede si coloca un directorio relativo en PYTHONPATH y luego cambia de directorio? ¿Qué pasa si ''foo.py'' es un enlace simbólico a ''bar.py''? ¿Esperas que los dos también se dupliquen? ¿Qué pasa si no son enlaces simbólicos, sino solo copias exactas? Agregar reglas complejas para tratar de hacer algo conveniente en circunstancias ambiguas significa que hace algo muy inconveniente para otras personas. (Python zen 12: en vista de la ambigüedad, rechaza la tentación de adivinar).
Python hace algo simple aquí, y es su responsabilidad asegurarse de que el entorno esté configurado correctamente. Ahora, podría argumentar que no es una buena idea colocar el directorio actual en PYTHONPATH
por defecto, incluso podría estar de acuerdo con usted, pero dado que está allí, debería seguir el mismo conjunto de reglas coherentes que otras entradas de ruta. . Si está destinado a ejecutarse desde un directorio arbitrario, su aplicación siempre puede eliminar el directorio actual de sys.path
comenzando con sys.path.remove('''')
.
Es un defecto menor del sistema de módulos actual.
Al importar el módulo , lo hace desde el espacio de nombre actual, que no tiene nombre. los valores dentro de este espacio de nombres son los mismos que los del paquete , pero el intérprete no puede saberlo.
Al importar package.module , importa el módulo desde el espacio de nombres del paquete .
Esta es la razón por la cual main.py debe estar fuera del paquete. Muchos módulos tienen esta organización:
package /
main.py
package /
sub_package1/
sub_package2/
sub_package3/
module1.py
module2.py
Al llamar solo a main.py, asegúrese de que los espacios de nombres estén configurados correctamente, también conocido como el espacio de nombres actual es main.py. Es imposible llamar a la importación module1.py en module2.py. Necesitarás llamar a import package.module1 . Hace las cosas más simples y homogéneas.
Y sí, importe la carpeta actual ya que la carpeta anónima actual era una mala idea. Es un PITA si va más allá de unas pocas secuencias de comandos. Pero como Python comenzó allí, no fue completamente sin sentido.