6.4. Utilisation de sys.modules

Les modules, comme tout le reste en Python, sont des objets. Une fois qu'il a été importé, vous pouvez toujours obtenir une référence à un module à travers le dictionnaire global sys.modules.

Exemple 6.12. Présentation 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 Le module sys contient des informations système, comme la version de Python que vous utilisez (sys.version ou sys.version_info) et des options système comme la profondeur maximale de récursion autorisée (sys.getrecursionlimit() et sys.setrecursionlimit()).
2 sys.modules est un dictionnaire qui contient tous les modules qui ont été importés depuis que Python a été démarré. La clé est le nom de module, la valeur est l’objet module. Notez que cela comprend plus que les modules que votre programme a importé. Python charge certains modules au démarrage et si vous êtes dans une IDE Python, sys.modules contient tous les modules importés par tous les programmes que vous avez exécutés dans l’IDE.

Cet exemple présente l'utilisation de sys.modules.

Exemple 6.13. Utilisation 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 Au fur et à mesure que des nouveaux modules sont importés, ils sont ajoutés à sys.modules. Cela explique pourquoi importer le même module deux fois est très rapide : Python a déjà chargé et mis en cache le module dans sys.modules, donc l’importer une deuxième fois n’est qu’une simple consultation de dictionnaire.
2 A partir du nom (sous forme de chaîne) de n’importe quel module déjà importé, vous pouvez obtenir une référence au module lui-même du dictionnaire sys.modules.

L'exemple suivant montre l'utilisation de l'attribut de classe __module__ avec le dictionnaire sys.modules pour obtenir une référence vers le module dans lequel la classe est définie.

Exemple 6.14. L’attribut de classe __module__

>>> from fileinfo import MP3FileInfo
>>> MP3FileInfo.__module__              1
'fileinfo'
>>> sys.modules[MP3FileInfo.__module__] 2
<module 'fileinfo' from 'fileinfo.pyc'>
1 Chaque classe Python a un attribut de classe __module__ prédéfini, dont la valeur est le nom du module dans lequel la classe est définie.
2 En combinant cela au dictionnaire sys.modules vous pouvez obtenir une référence au module dans lequel la classe est définie.

Maintenant vous pouvez comprendre l'utilisation de sys.modules dans fileinfo.py, le programme d'exemple présenté au Chapitre 5. Cet exemple montre cette partie du code.

Exemple 6.15. sys.modules dans fileinfo.py

    def getFileInfoClass(filename, module=sys.modules[FileInfo.__module__]):       1
        "get file info class from filename extension"                             
        subclass = "%sFileInfo" % os.path.splitext(filename)[1].upper()[1:]        2
        return hasattr(module, subclass) and getattr(module, subclass) or FileInfo 3
1 Ceci est une fonction avec deux arguments, filename est obligatoire, mais module est optionnel et est par défaut le module qui contient la classe FileInfo. Cela peut sembler peu efficace si on pense que Python évalue l’expression sys.modules à chaque fois que la fonction est appelée. En fait, Python n’évalue les expressions par défaut qu’une fois, la première fois que le module est importé. Comme nous le verrons plus loin nous n’appelons jamais cette fonction avec un argument module, module sert donc de constante au niveau de la fonction.
2 Nous détaillerons cette ligne plus tard, après avoir étudié le module os. Pour l’instant retenez simplement que subclass obtient le nom d’un classe, comme MP3FileInfo.
3 Vous connaissez déjà getattr, qui obtient une référence a un objet par son nom. hasattr est une fonction complémentaire qui vérifie si un objet possède un attribut particulier. Dans le cas présent, si un module possède une classe particulière (bien que cela fonctionne pour tout objet et tout attribut, tout comme getattr). En français, cette ligne de code dit «si le module a la classe nommée par subclass alors la retourner, sinon retourner la classe de base FileInfo».

Pour en savoir plus