módulo de importación de Python desde un paquete

estructura de carpetas:

 main.py packages  __init__.py mod.py 

py principal

 import packages print packages.mod.hello() 

mod.py:

 def hello(): return 'hello' 

__init__.py:

 from packages import mod 

Si ejecuto main.py , no obtengo ningún error. Pero si edito __init__.py a 'from packages import *' , __init__.py este error: AttributeError: el objeto ‘módulo’ no tiene atributo ‘mod’

No estoy preguntando cómo hacer que 'print' comando 'print' funcione. Puedo usar otra syntax de 'import' en main.py para hacer que funcione. La pregunta es: tengo curiosidad acerca de que 'from packages import mod' en __init__.py . Si puedo import mod entonces cuando reemplacé para import * , lo que significa importar todo, ¿por qué me aparece un error?

Entonces, ¿qué significa realmente la from packages import * __init__.py ?

¿Alguien puede ayudar? Gracias

Respuesta corta

Entonces, ¿qué significa realmente la from packages import * __init__.py ?

El __init__.py importa solo.

Explicación

Solo puedes importar módulos, no paquetes. Los paquetes son solo contenedores para módulos o subpaquetes. Cuando “importa” un paquete, en realidad importa el módulo __init__.py .

El __init__.py con este contenido:

 from packages import mod 

importa el mod del modulo en __init__.py . Por lo tanto, estará disponible en su main.py través de packages.mod (recuerde que los packages están representados por __init__.py ).

Cuando cambias el contenido de __init__.py a:

 from packages import * 

Usted está importando el módulo __init__.py , el mismo archivo en el que se encuentra. Esto funciona (una segunda importación solo activa una búsqueda en sys.modules ) pero no le brinda el contenido de mod .

Esto significa que puedes usar:

 from module import * 

pero no puedes usar esto sensiblemente con un __init__.py vacío:

 from package import * 

Porque el package está representado en realidad por __init__.py y todavía no hay nada en él. Puede verificar esto (interactivamente o en archivo):

 >>> import packages >>> print(packages)  

En __init__.py puedes escribir:

 from packages.mod import * 

y luego en main.py :

 print packages.hello() 

trabajos. Debido a que la función hello() encuentra ahora en el espacio de nombres global del archivo __init__.py .

Como lo menciona mozman en la respuesta, puede usar __all__ en __init__.py para enumerar los módulos que deben importarse si se usa from packages import * . Esto está diseñado para este caso.

El __init__.py tiene solo este contenido:

 __all__ = ['mod'] 

Ahora puedes hacer esto en main.py :

 from packages import * print mod.hello() 

Si extiendes tu __init__.py :

 __all__ = ['mod'] from packages import * 

Puedes hacer esto en main.py :

 import packages print packages.mod.hello() 

Pero si elimina la from packages import * de __init__.py :

 __all__ = ['mod'] 

Obtendrá un error:

 AttributeError: 'module' object has no attribute 'mod' 

porque __all__ solo se usa para el caso from packages import * . Ahora volvemos a las importaciones de __init__.py .

Ver también: En Python, ¿qué importa exactamente “importar *”?

agregando __all__ a los paquetes .__ init__:

 __all__ = ['mod'] from packages import * 

y el módulo ‘mod’ se importará, de lo contrario, ‘mod’ no se encuentra en el espacio de nombres de ‘paquetes’, pero no puedo explicar por qué ‘importar *’ sin __all__ no importa ‘mod’.

Puede cargar los módulos dentro de los mismos paquetes directamente. El siguiente código funciona y carga todos los módulos dentro de mod.py.

Dentro __init__.py

 from mod import * print hello() 

Importación eficiente – solo carga la función hola

 from mod import hello print hello() 

En su código, from packages import * le está diciendo al intérprete que busque módulos dentro de los packages (en el mismo directorio que __init__.py ). Pero allí no existe. __init__.py un directorio arriba del __init__.py . (Sospecho que mis terminologías están equivocadas)

Aquí hay una referencia que explica cómo cargar el paquete que contiene.

LO ENCONTRÉ

Fue muy interesante leer sobre los mecanismos de importación de Python. Ref1 Ref2 Ref3

Aparentemente los módulos parentales se cargan primero. Por ejemplo, Ref3 establece que el import mod código dentro de __init__.py se interpreta automáticamente como packages.mod . Ahora tengo que averiguar qué sucede si escribes import packages.mod . Ref1 está más actualizado con las convenciones de python3. Consulte para más información. Espero que esto te ayude.