En Python, si desea importar mediante programación de un módulo, usted puede hacer:

module = __import__('module_name')

Si quieres importar un submódulo, usted podría pensar que sería una simple cuestión de:

module = __import__('module_name.submodule')

Por supuesto, esto no funciona, usted acaba de conseguir el module_name de nuevo. Usted tiene que hacer:

module = __import__('module_name.submodule', fromlist=['blah'])

¿Por qué? El valor real de fromlist no importa en absoluto, mientras que es no vacío. ¿Cuál es el punto de requerir un argumento, a continuación, ignorando sus valores?

La mayoría de las cosas en Python parece ser hecho por una buena razón, pero para la vida de mí no puedo encontrar ninguna explicación razonable para este comportamiento de existir.

OriginalEl autor ieure | 2010-04-27

3 Comentarios

  1. 118

    De hecho, el comportamiento de __import__() es completamente debido a la aplicación de la import declaración, que llama a __import__(). Hay básicamente cinco formas ligeramente diferentes __import__() puede ser llamado por 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 la «izquierda» del módulo de objeto a la «izquierda» nombre: pkg. Después de import pkg.mod que usted puede hacer pkg.mod.func() porque el import declaración introducido el nombre local pkg, que es un módulo objeto que tiene un mod atributo. Así, el __import__() función para devolver la «izquierda» del módulo objeto de modo que se pueda asignar a pkg. Los dos sentencias de importación por lo tanto se traducen en:

    pkg = __import__('pkg')
    pkg = __import__('pkg.mod')

    En el tercer, cuarto y quinto caso, el import declaración tiene que hacer más trabajo: asignar a (potencialmente) de varios nombres, el que ha de llegar desde el módulo de objeto. El __import__() función sólo puede devolver un objeto, y no hay ninguna razón real para hacerlo recuperar cada uno de los nombres del módulo objeto (y haría que la aplicación mucho más complicado.) 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 los módulos en que el paquete de que ya no son importados, como lo son en el tercer y el quinto caso. El __import__() función de las necesidades de saber que mod y mod2 son los nombres que la import declaración se quiere tener acceso, por lo que se puede ver si son módulos de e intente importar demasiado. Por lo que la llamada está más cerca:

    tmp = __import__('pkg', fromlist=['mod', 'mod2'])
    mod = tmp.mod
    mod2 = tmp.mod2

    que hace que __import__() para tratar de carga y pkg.mod y pkg.mod2 así como pkg (pero si mod o mod2 no existe, no es un error en el __import__() de la llamada; la producción de un error de la izquierda a la import declaración). Pero aún así no es la cosa correcta para la cuarta y quinta ejemplo, porque si la llamada hubiera sido así:

    tmp = __import__('pkg.mod', fromlist=['submod'])
    submod = tmp.submod

    luego tmp acabaría siendo pkg, como antes, y no la pkg.mod módulo que desea obtener la submod atributo. La aplicación podría haber decidido a hacer lo que el import instrucción de trabajo extra, dividiendo el nombre del paquete en . como el __import__() función ya lo hace y la que atraviesan los nombres, pero esto significaba duplicar el esfuerzo. En vez de eso, la aplicación hecha __import__() devolver el más a la derecha módulo en lugar de la más a la izquierda uno si y sólo si fromlist se pasa y no vacío.

    (El import pkg as p y from pkg import mod as m sintaxis no cambia nada sobre esta historia, salvo que los nombres asignados a — la __import__() función ve nada diferente cuando as se utiliza, todo permanece en el import declaración de aplicación.)

    OriginalEl autor Thomas Wouters

  2. 5

    Todavía me siento raro cuando he leído la respuesta, así que probé con el siguiente código de las muestras.

    Primero, tratar de construir siguiente estructura de archivos:

    tmpdir
      |A
         |__init__.py
         | B.py
         | C.py

    Ahora es un package, y B o C es un module. Así que cuando tratamos de algún código como estos en ipython:

    Segundo, ejecutar el código de ejemplo en ipython:

      In [2]: kk = __import__('A',fromlist=['B'])
    
      In [3]: dir(kk)
      Out[3]: 
      ['B',
       '__builtins__',
       '__doc__',
       '__file__',
       '__name__',
       '__package__',
       '__path__']

    Parece que el fromlist funciona como esperábamos. Pero las cosas se vuelven cable cuando tratamos de hacer las mismas cosas en un module. Supongamos que tenemos un módulo llamado C. py y código en él:

      handlers = {}
    
      def hello():
          print "hello"
    
      test_list = []

    Por lo que ahora tratamos de hacer la misma cosa en él.

      In [1]: ls
      C.py
    
      In [2]: kk = __import__('C')
    
      In [3]: dir(kk)
      Out[3]: 
      ['__builtins__',
       '__doc__',
       '__file__',
       '__name__',
       '__package__',
       'handlers',
       'hello',
       'test_list']

    Así que cuando queremos importar el test_list, ¿funciona?

      In [1]: kk = __import__('C',fromlist=['test_list'])
    
      In [2]: dir(kk)
      Out[2]: 
      ['__builtins__',
       '__doc__',
       '__file__',
       '__name__',
       '__package__',
       'handlers',
       'hello',
       'test_list']

    Como el resultado de la muestra, cuando tratamos de utilizar fromlist en un module en lugar de un package, el fromlist param no ayuda en absoluto, porque module ha sido compilada. Una vez importado, no hay manera de ignorar los otros.

    OriginalEl autor zhkzyth

  3. 2

    La respuesta se puede encontrar en la documentación para __import__:

    La fromlist debe ser una lista de nombres para emular from name import ..., o una lista vacía para emular import name.

    Al importar un módulo de un paquete, tenga en cuenta que __import__('A.B', ...) devuelve Un paquete de cuando fromlist está vacía, pero su submódulo B cuando fromlist no está vacío.

    Así que, básicamente, eso es sólo cómo la aplicación de __import__ funciona: si desea que el submódulo, pasar un fromlist que contiene algo que desea importar en el submódulo, y la aplicación si __import__ es tal que el submódulo se devuelve.

    Más explicación

    Creo que la semántica de existir a fin de que los más relevantes módulo se devuelve. En otras palabras, decir que tengo un paquete de foo con el módulo bar con la función baz. Si Yo:

    import foo.bar

    A continuación, me refiero a baz como

    foo.bar.baz()

    Esto es como __import__("foo.bar", fromlist=[]).

    Si en lugar de importar con:

    from foo import bar

    A continuación, me refiero a baz como
    de la barra.baz()

    Que sería similar a __imoort__("foo.bar", fromlist=["something"]).

    Si hago:

    from foo.bar import baz

    A continuación, me refiero a baz como

    baz()

    Que es como __import__("foo.bar", fromlist=["baz"]).

    Así, en el primer caso, yo tendría que usar el nombre completo, por lo tanto __import__ devuelve el primer nombre del módulo que usted usaría para referirse a la importación de elementos, que se foo. En el último caso, bar es el más específico de módulo que contiene la importación de elementos, así que tiene sentido que __import__ devolvería la foo.bar módulo.

    El segundo caso es un poco raro, pero supongo que fue escrito de esa manera apoyar a la importación de un módulo mediante la from <package> import <module> sintaxis, y en ese caso bar es todavía el más específico módulo de retorno.

    Diciendo: «que así es como la ejecución de obras» no responde a mi pregunta. ¿Por qué se hace de esa manera? Diciendo: «para emular el nombre de importación …» formulario está más cerca, pero, ¿bajo qué circunstancias usted necesita? El fromlist no tiene una pizca de diferencia en el modo en import en realidad funciona, así que no veo donde hay un caso en el que tendría que pasar para emular nada, excepto lo que debería ser obvio: el comportamiento de la función.
    Tienes razón, es una petición de principio. He actualizado mi respuesta para dar una información más relevante de la respuesta.

    OriginalEl autor mipadi

Dejar respuesta

Please enter your comment!
Please enter your name here