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>>> print'\n'.join(sys.modules.keys())win32api
os.path
os
exceptions
__main__
ntpath
nt
sys
__builtin__
site
signal
UserDict
stat
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()).
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
IDEPython, 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>>> 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"]<module 'fileinfo' from 'fileinfo.pyc'>
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.
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__'fileinfo'>>> sys.modules[MP3FileInfo.__module__]<module 'fileinfo' from 'fileinfo.pyc'>
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.
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__]): "get file info class from filename extension"
subclass = "%sFileInfo" % os.path.splitext(filename)[1].upper()[1:] return hasattr(module, subclass) and getattr(module, subclass) or FileInfo
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.
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.
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».