16.6. Importación dinámica de módulos

Bien, basta de filosofar. Hablemos sobre la importación dinámica de módulos.

Miremos primero la manera normal de importar módulos. La sintaxis de import módulo localiza por su nombre el módulo especificado en la ruta de búsqueda y lo importa. Incluso puede importar varios módulos de una vez de esta manera, con una lista separada por comas. Hicimos esto en la primera línea del script de este capítulo.

Ejemplo 16.13. Importación de varios módulos a la vez


import sys, os, re, unittest 1
1 Esto importa cuatro módulos de una vez: sys (con las funciones del sistema y acceso a parámetros de línea de órdenes), os (con funciones del sistema operativo como listado de directorios), re (para las expresiones regulares) y unittest (para las pruebas unitarias).

Ahora haremos lo mismo pero de forma dinámica.

Ejemplo 16.14. Importación dinámica de módulos

>>> sys = __import__('sys')           1
>>> os = __import__('os')
>>> re = __import__('re')
>>> unittest = __import__('unittest')
>>> sys                               2
>>> <module 'sys' (built-in)>
>>> os
>>> <module 'os' from '/usr/local/lib/python2.2/os.pyc'>
1 La función incorporada __import__ cumple el mismo objetivo de la sentencia import, pero es una función y toma una cadena como argumento.
2 Ahora la variable sys es el módulo sys, igual que si hubiera escrito import sys. La variable os es ahora el módulo os, etc..

Así que __import__ importa un módulo, pero toma una cadena como argumento para hacerlo. En este caso el módulo que importó era sólo una cadena fija, pero podría ser también una variable o el resultado de invocar una función. Y la variable a la que asignemos el módulo tampoco tiene por qué coincidir con el nombre del módulo. Podría importar varios módulos y asignarlos a una lista.

Ejemplo 16.15. Importación de una lista de módulos de forma dinámica

>>> moduleNames = ['sys', 'os', 're', 'unittest'] 1
>>> moduleNames
['sys', 'os', 're', 'unittest']
>>> modules = map(__import__, moduleNames)        2
>>> modules                                       3
[<module 'sys' (built-in)>,
<module 'os' from 'c:\Python22\lib\os.pyc'>,
<module 're' from 'c:\Python22\lib\re.pyc'>,
<module 'unittest' from 'c:\Python22\lib\unittest.pyc'>]
>>> modules[0].version                            4
'2.2.2 (#37, Nov 26 2002, 10:24:37) [MSC 32 bit (Intel)]'
>>> import sys
>>> sys.version
'2.2.2 (#37, Nov 26 2002, 10:24:37) [MSC 32 bit (Intel)]'
1 moduleNames es una lista de cadenas. Nada del otro mundo si exceptuamos que las cadenas resultan ser los nombres de módulos que podríamos importar, si así quisiéramos.
2 Sorpresa, queríamos importarlos, y lo hicimos relacionando la función __import__ sobre la lista. Recuerde que esto toma cada elemento de la lista (moduleNames) e invoca la función (__import__) una y otra vez, sobre cada elemento de la lista; construye una lista de valores de retorno y devuelve el resultado.
3 Así que partiendo de una lista de cadenas hemos creado una lista de módulos. (Las rutas de usted pueden ser diferentes, dependiendo del sistema operativo, dónde haya instalado Python, la fase de la luna, etc.).
4 Para comprobar que estos son módulos reales, veamos algunos de sus atributos. Recuerde que modules[0] es el módulo sys, así que modules[0].version es sys.version. También están disponibles todos los otros atributos y métodos de esos módulos. No hay nada mágico respecto a la sentencia import, y tampoco respecto a los módulos. Los módulos son objetos. Todo es un objeto.

Ahora debería ser capaz de juntar todo esto e imaginarse lo que hace la mayoría del código de ejemplo de este capítulo.