De hecho, el comportamiento de __import__()
se debe enteramente a la implementación de la declaración import
, que llama al __import__()
. Hay básicamente cinco maneras ligeramente diferentes __import__()
se puede llamar import
(con dos categorías principales):
import pkg
import pkg.mod
from pkg import mod, mod2
from pkg.mod import func, func2
from pkg.mod import submod
En la primera y el segundo caso, el import
declaración debe asignar el objeto módulo "más a la izquierda" a el nombre "más a la izquierda": pkg
. Después de import pkg.mod
puede hacer pkg.mod.func()
porque la declaración import
introdujo el nombre local pkg
, que es un objeto de módulo que tiene un atributo mod
. Por lo tanto, la función __import__()
tiene que devolver el objeto del módulo "más a la izquierda" para que pueda asignarse a pkg
. Por tanto, estas dos declaraciones de importación se traducen en:
pkg = __import__('pkg')
pkg = __import__('pkg.mod')
En el tercero, cuarto y quinto caso, la declaración import
tiene que hacer más trabajo: tiene que asignar a (potencialmente) múltiples nombres, los cuales tiene que llegar desde el objeto del módulo La función __import__()
solo puede devolver un objeto, y no hay una razón real para hacer que recupere cada uno de esos nombres del objeto del módulo (y la implementación sería mucho más complicada). Así que el enfoque simple sería algo así como (para el tercer caso):
tmp = __import__('pkg')
mod = tmp.mod
mod2 = tmp.mod2
sin embargo, eso no funcionará si pkg
es un paquete y mod
o mod2
son módulos en ese paquete que no están ya importada, ya que están en el tercer y quinto caso. La función __import__()
necesita saber que mod
y mod2
son nombres a los que la declaración import
querrá tener acceso, para que pueda ver si son módulos e intentar importarlos también.Así que la llamada está más cerca de:
tmp = __import__('pkg', fromlist=['mod', 'mod2'])
mod = tmp.mod
mod2 = tmp.mod2
que provoca __import__()
para tratar de carga pkg.mod
y pkg.mod2
, así como pkg
(pero si no existen mod
o mod2
, no es un error en la llamada __import__()
; producir una de error se deja a la declaración import
) pero que todavía no es lo correcto para el cuarto y quinto ejemplo, porque si la llamada fuera así:.
tmp = __import__('pkg.mod', fromlist=['submod'])
submod = tmp.submod
continuación tmp
terminaría siendo pkg
, como antes, y no el módulo pkg.mod
del que desea obtener el atributo submod
. La implementación podría haber decidido hacerlo para que la declaración import
haga un trabajo extra, dividiendo el nombre del paquete en .
como lo hace la función __import__()
y recorriendo los nombres, pero esto habría significado duplicar parte del esfuerzo. Así que, en cambio, la aplicación hace __import__()
retorno del derecho más - módulo en lugar de la más a la izquierda uno si y sólo si fromlist se pasa y no está vacío.
(El import pkg as p
y from pkg import mod as m
sintaxis no cambia nada de esta historia, excepto la que los nombres locales se asignan a - la función __import__()
ve nada diferente cuando se utiliza as
, todo permanece en la aplicación import
comunicado.)
Decir "así es como funciona la implementación" no responde mi pregunta. ¿Por qué funciona de esa manera? Diciendo que "emular la importación desde el nombre ..." está más cerca, ¿pero bajo qué circunstancias lo necesitarías? La lista de salida no hace una pizca de diferencia de cómo __import__ realmente funciona, por lo que no veo dónde hay un caso donde tendría que pasarlo para emular cualquier cosa, excepto cuál debería ser el comportamiento obvio de la función. – ieure
Tienes razón, me hace la pregunta. Actualicé mi respuesta para dar una respuesta más relevante. – mipadi