6.4. Uso de sys.modules

Los módulos son objetos, como todo lo demás en Python. Una vez importado, siempre puede obtener una referencia a un módulo mediante el diccionario global sys.modules.

Ejemplo 6.12. Presentación de sys.modules

>>> import sys                          1
>>> print '\n'.join(sys.modules.keys()) 2
win32api
os.path
os
exceptions
__main__
ntpath
nt
sys
__builtin__
site
signal
UserDict
stat
1 El módulo sys contiene información sobre el sistema, tal como la versión de Python que ejecutamos (sys.version o sys.version_info), y opciones del sistema tales como el nivel de recursión máximo permitido (sys.getrecursionlimit() y sys.setrecursionlimit()).
2 sys.modules es un diccionario que contiene todos los módulos que se han importado desde que arrancara Python; la clave es el nombre del módulo, el valor es el objeto del módulo. Advierta que aquí hay más módulos de los que su programa ha importado. Python carga algunos módulos durante el arranque, y si usa un IDE para Python, sys.modules contendrá todos los módulos importados por todos los programas que esté ejecutando dentro del IDE.

Este ejemplo demuestra el uso de sys.modules.

Ejemplo 6.13. Uso de sys.modules

>>> import fileinfo         1
>>> print '\n'.join(sys.modules.keys())
win32api
os.path
os
fileinfo
exceptions
__main__
ntpath
nt
sys
__builtin__
site
signal
UserDict
stat
>>> fileinfo
<module 'fileinfo' from 'fileinfo.pyc'>
>>> sys.modules["fileinfo"] 2
<module 'fileinfo' from 'fileinfo.pyc'>
1 Los módulos nuevos van siendo añadidos a sys.modules según son importados. Esto explica por qué importar un módulo por segunda vez es muy rápido: Python ya lo ha cargado y lo tiene en caché en sys.modules, de manera que importarlo la segunda vez no cuesta más que una búsqueda en un diccionario.
2 Dado el nombre (como cadena) de cualquier módulo importado previamente, podemos obtener una referencia al propio módulo mediante el diccionario sys.modules.

El siguiente ejemplo muestra el uso del atributo de clase __module__ con el diccionario sys.modules para obtener una referencia al módulo en el que está definida una clase.

Ejemplo 6.14. El atributo de clase __module__

>>> from fileinfo import MP3FileInfo
>>> MP3FileInfo.__module__              1
'fileinfo'
>>> sys.modules[MP3FileInfo.__module__] 2
<module 'fileinfo' from 'fileinfo.pyc'>
1 Cada clase de Python tiene un atributo de clase __module__ incorporado, que consiste en el nombre del módulo en que se definió la clase.
2 Combinando esto con el diccionario sys.modules, podemos obtener una referencia al módulo en que se definió la clase.

Ahora ya está listo para comprobar el uso de sys.modules en fileinfo.py, el programa de ejemplo presentado en Capítulo 5. Este ejemplo muestra esa porción de código.

Ejemplo 6.15. sys.modules en fileinfo.py

    def getFileInfoClass(filename, module=sys.modules[FileInfo.__module__]):       1
        "obtener la clase de información de un fichero por su extensión"                             
        subclass = "%sFileInfo" % os.path.splitext(filename)[1].upper()[1:]        2
        return hasattr(module, subclass) and getattr(module, subclass) or FileInfo 3
1 Ésta es una función con dos argumentos; filename es obligatoria, pero module es opcional y por omisión es el módulo que contiene la clase FileInfo. Esto no parece eficiente, porque es de esperar que Python evalúe la expresión sys.modules cada vez que se llama a la función. En realidad, Python evalúa las expresiones por omisión sólo una vez, la primera en que se importa el módulo. Como verá más adelante, nunca se llama a esta función con un argumento module, así que module sirve como constante en la función.
2 Volveremos a esta línea más adelante, tras sumergirnos en el módulo os. Por ahora, creáse que subclass acaba siendo el nombre de una clase, como MP3FileInfo.
3 Ya conoce getattr, que obtiene una referencia a un objeto por su nombre. hasattr es una función complementaria, que comprueba si un objeto tiene un atributo en particular; en este caso, si un módulo tiene una clase en particular (aunque funciona con cualquier objeto y cualquier atributo, igual que getattr). En idioma humano el código de esta línea dice, “Si este módulo contiene la clase denominada subclass entonces devuélvela, en caso contrario devuelve la clase base FileInfo.

Lecturas complementarias sobre módulos