Ce chapitre se concentre sur les modules de Python et sur les modalités d’importation des données des modules dans l’environnement de travail.
L’objectif de ce document est de souligner l’importance d’un code modulaire, c’est à dire d’un code qui :
- puisse être utilisé dans plusieurs programmes ;
- puisse être documenté précisément ;
- soit suffisamment compact pour être étudié avec soin et en particulier testé.
Qu’est-ce qu’un module ?
- Quand la taille du code augmente, il peut être pratique de le diviser en entités organisées qui peuvent continuer à interagir.
- Un module permet aussi de se créer une « boite à outils » contenant des fonctions appelées depuis plusieurs programmes.
- Finalement, un module permet de bénéficier du travail déjà effectué, maximisant ainsi la réutilisabilité du code.
Modules et fichiers
À cette fin, chaque fichier est considéré comme un module individuel,
et réciproquement. Le nom de fichier d’un module est le nom du module
auquel on ajoute l’extension .py
.
Un module peut contenir tout objet Python: variables, fonctions, classes, $\ldots$
Chemin de recherche et recherche de fichiers
L’importation de modules requiert un processus nommé chemin de recherche . C’est une procédure de recherche dans un ensemble de répertoires (dossiers) du système de fichiers — le résultat de cette recherche dépend donc de l’installation de Python et du système d’exploitation utilisé — pour trouver le fichier module:
|
|
Dans le cas où la recherche d’un module échoue, une exception est levée par l’interpréteur :
|
|
Puisque le chemin de recherche consiste à construire une liste de
répertoires (dossiers), il est possible de la modifier. La méthode de liste append()
permet d’importer un module situé dans un répertoire absent du chemin de
recherche:
|
|
Portée des variables et espaces de noms
La portée d’un identificateur est la portion du programme à laquelle sa déclaration s’applique. On emploie également le terme de visibilité .
Les variables définies dans une fonction ont une portée locale, celles définies au plus haut niveau d’un module ont une portée globale.
|
|
|
|
Il est donc possible de « masquer » une variable globale, en utilisant une variable locale de même nom.
Import de modules
L’instruction import
L’import d’un module nécessite l’emploi de l’instruction import
. La syntaxe
est la suivante :
|
|
Il est possible d’importer plusieurs modules :
|
|
Lorsque l’interpréteur rencontre un import
, le chemin de recherche est
utilisé pour accéder au module. Si celui-ci est trouvé, il est importé. Comme annoncé ci-dessus, les
règles de portée s’appliquent : si l’import se situe au niveau du module, sa
portée est globale, s’il se situe dans une fonction, sa portée est locale.
.
doit être utilisée afin d’utiliser ces objets.
|
|
Comment accéder à la liste des objets contenus dans un module ?
On peut utiliser la fonction dir
:
|
|
Comment obtenir l’aide d’un module ?
On peut utiliser la fonction help
:
|
|
Comment obtenir la liste de tous les modules importés par un programme ?
|
|
L’expression from … import
Il est possible d’importer des objets particuliers d’un module dans le programme. L’objet appartient alors réellement à l’espace de nom du programme.
|
|
Remarque
Ce type d’import peut présenter de réels dangers dans un programme dont le nombre de lignes est important et dont le développement s’effectue sur une longue durée. Que se passe-t-il si, dans le programme principal, un attribut ou une fonction portent le même nom que l’élément importé ?
|
|
Remarque
Il existe une façon encore plus dangereuse d’utiliser l’expression from ... import ...
:
|
|
Tous les objets contenus dans le module sont alors ajoutés à l’espace de nom globale du programme.
from nom_module import *
!
L’instruction import … as
Il arrive que l’on souhaite importer un module ou un attribut de module portant un nom déjà employé dans l’application, ou que ce nom ne convienne pas parce qu’il est trop long. On peut changer le nom lié localement du module et procéder ensuite comme avec le nom complet :
|
|
Import vs chargement
Exemple de création d’un module
- Dans le fichier
demo.py
:
|
|
- Dans l’interpréteur intéractif, lancé depuis le dossier dans lequel on a enregistré le module
demo.py
:
|
|
Mécanisme de gestion des exceptions
Lorsqu’un problème intervient lors de l’exécution d’un programme (division par zéro, tentative d’ouverture d’un fichier qui n’existe pas, erreur de syntaxe, etc.), l’interpréteur passe dans un mode particulier dans lequel il stoppe l’exécution du programme en cours et affiche une erreur :
|
|
Message d’erreur
Le message affiché contient le traceback
, c’est à dire la pile d’appel — le chemin parcouru par l’interpréteur pour atteindre l’erreur (soit la liste des fonctions traversées pour atteindre l’erreur).
Ce message comporte le type d’exception levée (ZeroDivisionError
, IOError
, NameError
, SyntaxError
, etc.) et un message qui décrit le problème rencontré.
Remarque
Dans le cas d’une erreur de syntaxe, le message d’erreur indique même où est détectée l’erreur à l’aide d’une flèche (en fait, elle se trouve généralement juste avant l’endroit pointé par la flèche).
Exemple : Gestion des entrées du clavier
|
|
Le gestion des exceptions repose sur quelques mots clés : try
, except
, else
et finally
et sur une liste de types d’exceptions dont la liste peut être
consultée dans la documentation en ligne de Python :
try
: le bloc de code qui suit ce mot clé est exécuté séquentiellement. En cas de problème, l’exécution est interrompue et l’interpréteur passe au bloc d’instructions suivant le mot clé except.except NomErreur
: ce bloc d’instructions est exécuté si une erreur a été détectée dans le bloc try et si son type correspond à NomErreur. Plusieurs clauses except peuvent être utilisées. Il n’est pas nécessaire d’indiquer le type de l’erreur (tous les types sont alors traités de façon identique).else
: cette directive permet d’isoler dans la partie try la ou les instructions qui peuvent poser problème. Toutes les instructions suivantes (qui ne doivent donc être exécutées que si aucun problème intervient) peuvent être placées dans le bloc else.finally
: le bloc qui suit est exécuté dans tous les cas de figure, qu’une exception ait été levée ou pas. C’est donc ici que l’on peut s’assurer qu’un fichier ouvert dans le bloc try est correctement fermé, quoi qu’il arrive.
Exemple : Prise en compte de plusieurs erreurs
|
|
Utilisation de else
|
|
Les exceptions dans la définition d’une fonction
|
|
Tout fichier manipulé doit être correctement fermé. Il n’est donc pas
envisageable d’utiliser la fonction open
sans gérer les exceptions. Utiliser
les instructions try
, except
et finally
peut cependant apparaître
contre-productif (cela fait beaucoup de code pour une action courante). with
permet de manipuler les fichiers en étant certain qu’ils seront fermés
correctement, quoi qu’il arrive.
|
|
Application
-
Écrire un module nommé
convert_temp
contenant les fonctions réalisant les conversions entre des températures exprimées en degrés Celsius, degrés Fahrenheit et Kelvin :C2F
,F2C
,C2K
,K2C
,F2K
andK2F
. -
Appeler ces fonctions depuis un autre programme.