• Aucun résultat trouvé

Fonctions, scripts et modules

5.3. Modules et paquetages 1 Modules.

les instructions import, from. Un module est associé à un fichier avec l’extension .py. Le module porte le nom du fichier et peut contenir des définitions de fonction, de variables ou de classe, aussi bien que des instructions exécutables. Ces instructions sont destinées à initialiser le module et ne sont exécutée qu’une seule fois à la première importation du module.

Chaque module possède sa propre table de symboles privée.

On peut accéder aux variables globales d’un module avec la même notation que celle employée pour se référer à ses fonctions :nommodule.nomvariable.

Les noms du module importé sont placés dans la table globale de symboles du module importa- teur.

Pour importer et utiliser un module :

1 >>> import random, math

2 >>> random.randint(0,10)

3 >>> math.pi

On peut aussi importer un (ou des) nom(s) particulier(s) d’un module. Dans ce cas, ces élément sont directement référencés par leur nom : randint, choice sans qu’il soit nécessaire de les préfixer par le nom du module comme ci-dessous :

1 >>> from random import (randint,choice)

2 >>> randint(0,10)

3 >>> choice(range(100))

1 >>> import random as rand

2 >>> rand.randint(1, 10)

Il y a une variante pour importer tous les noms d’un module, excepté ceux qui commencent par un tiret-bas (déconseillé) :

1 >>> from random import *

2 >>> choice(500)

La fonction reload(). Dans une sessionPython, la première fois qu’un module est importé par l’instructionimport moduleoufrom module import x,y, le module est compilé (à moins qu’un fichier bytecodemodule.pyc dont la date de dernière modification est plus récente que celle du fichier module.py ne soit présent dans le même répertoire). Si une autre instruction import module est rencontrée au cours de la même session, le module n’est pas recompilé. Bien souvent, en cours de développement, le module module.py est modifié. Dans la session Python, le re-importer pour prendre en compte ces modifications est sans effet puisqu’il n’est pas recompilé. Il faut alors utiliser la fonctionreload(module)ce qui a pour effet de compiler et re-importer module.

Ce faisant, les attributs importés individuellement parfrom module import x,yne seront pas mis à jour. Puisque cette instruction n’est qu’une affectation des objets x et y de module aux nomsxety, dans l’espace de nommage__main__. Ces deux objets n’ont pas été modifiés par le reload()et sont toujours référencés sous le nom__main__.xet__main__.y. Il faut donc les ré-importer parfrom module import x,y. Les noms__main__.xet__main__.yseront alors mis en correspondance avec les nouveaux objetsmodule.x etmodule.y . Cet exemple illustre ces différents points :

1 >>> import module

2 >>> dir(module)

3 ['__builtins__', ..., 'parfait', 'sqrt']

4 >>> module.parfait

5 <function parfait at 0xa439924>

6 >>> from module import parfait

7 >>> parfait

8 <function parfait at 0xa439924>

9 >>> reload(module)

10 <module 'module' from './module.pyc'>

11 >>> module.parfait

12 <function parfait at 0xa439bc4>

13 >>> parfait

14 <function parfait at 0xa439924>

15 >>> from module import parfait

5.3 Modules et paquetages 127

17 <function parfait at 0xa439bc4>

1 à 3 : importation demodule, qui contient une fonctionparfait;

4, 5 : la fonctionparfaitest à l’adresse..924;

6 : la fonctionmodule.parfaitest affectée au nom__main__.parfait;

7, 8 : son adresse est donc celle demodule.parfait;

9, 10 : compilation et importation demodule.py;

11, 12 : la fonctionmodule.parfaitest un nouvel objet, avec une nouvelle adresse..bc4; 13, 14 : la fonction pointée par le nom __main__.parfaitest toujours à la même (ancienne)

adresse ..924;

15 à 17 : le nom__main__.parfaitest réaffecté au (nouvel) objetmodule.parfaità la nou- velle adresse, l’ancienparfaitest détruit

5.3.2. Paquetages. Un paquetagePythonest une arborescence de paquetages et de modules. Un paquetage possède un répertoire racine dans lequel se trouve un fichier__init__.py. Usuel- lement un paquetage possède une unité et un cohérence interne, mais rien n’empêche un paque- tagePythonde contenir côte à côte une base de données de recette de cuisines et une bibliothèque de fonctions mathématiques.

Un paquetage peut se charger comme un module par l’instruction

1 >>> import paquetage

Dans ce cas on accède aux modules du paquetage par la notation usuellepaquetage.module. Le fichier__init__.pydu paquetage, qui se trouve à la racine du répertoire-paquetage, est un fichier scriptPythonordinaire exécuté au chargement du paquetage, dans lequel sont faites di- verses initialisations concernant le paquetage. On peut y trouver en particulier une liste

1 __all__=[mod1,mod2,...,var1,var2,...]

qui sera utilisée lors de l’instruction

1 >>> from paquetage import *

mod1,mod2, ...sont des noms de modules,var1, var2, ...sont des noms de variables. Rien n’empêche cependant d’importer un module existant qui n’est pas listé dans__all__ par une instruction explicite

5.3.3. Le chemin de recherche des paquetages et modules. Quand un module nommé

spamest importé, l’interpréteur recherche un fichier nomméspam.py – dans le répertoire courant, et puis

– dans la liste de répertoires indiquée par la variable d’environnementPYTHONPATH.

– dans un chemin d’accès par défaut, dépendant de l’installation ; sur Unix, c’est habituellement /usr/local/lib/python.

En fait, les modules sont recherchés dans la liste de répertoires donnée par la variablesys.path. Ainsi, si votre module karakoram se trouve dans un répertoire exotique, disons /home/pui- seux/vacances/pakistan, il vous suffit d’ajouter le nom de ce répertoire à la listesys.path:

1 >>> import sys

2 >>> sys.path.append('/home/puiseux/vacances/pakistan')

3 >>> import karakoram

5.3.4. Fichiers bytecode. Pour accélérer le temps de lancement, si un fichier appeléspam.pyc existe dans le répertoire où se trouvespam.py, il est supposé contenir une version du modulespam déjà compilée en bytecode.

Au lancement despam.py

– recherche despam.pyc(fichier déjà compilé en bytecode) dans le même répertoire quespam.py. – si spam.pyc existe, et si sa date de création est postérieur à celle de spam.py, alors il est

lancé.

– sinon,spam.pyest compilé etspam.pycest exécuté

Toutes les fois quespam.pyest compilé avec succès, une tentative est faite pour écrire la version compilée surspam.pyc.

Le contenu du fichierspam.pycest indépendant de la plate-forme, ainsi un répertoire de module dePython. Il peut être partagé par des machines d’architectures différentes.

5.3.5. Modules standard. Pythonest livré avec une bibliothèque de modules standard, dé- crite dans un document séparé,PythonLibrary Reference. Cette bibliothèque sera examinée plus en détail au chapitre7. Quelques modules standard de base :

math: fonctions et constantes mathématiques de base (sin, cos, exp, pi...). sys: passage d’arguments, gestion de l’entrée/sortie standard...

os : dialogue avec le système d’exploitation (e.g. permet de sortir de Python , lancer une commande en shell, puis de revenir àPython).

random: génération de nombres aléatoires.

time: permet d’accéder à l’heure de l’ordinateur et aux fonctions gérant le temps.

calendar: fonctions de calendrier.

profile : permet d’évaluer le temps d’exécution de chaque fonction dans un programme (profilage ou profiling en anglais).

5.4 Décorateurs 129 urllib2: permet de récupérer des données sur internet depuisPython.

Tkinter: interface python avec Tk (permet de créer des objets graphiques ; nécessite d’ins- taller Tk).

re: gestion des expressions régulières.

pickle: écriture et lecture de structuresPython(comme les dictionnaires par exemple).

doctest: un module pour le développement dirigé par la documentation, c’est à dire per- mettant d’écrire en même temps les tests et la documentation voir2.12 page 45.

5.4. Décorateurs

Un décorateurPythonest une fonction qui prend en paramètre une autre fonction, pour la modi- fier, lui ajouter des fonctionnalités, la substituer ou simplement exécuter un travail avant ou après l’avoir appelé.

Un décorateur nommé monDecorateur()est appelé en plaçant l’instruction@monDecorateur au dessus de la fonction ciblée.

Un exemple de décorateur pour rendre la comparaison de deux chaînes de caractères insensible à la casse :

1 def caseInsensitive(func) :

2 def minuscule(x) :

3 return func(*[a.lower() for a in x])

4

5 @caseInsensitive

6 def isEqual(x, y) :

7 return (x == y)

Comparons les chaînes de caractèresChomoLungaetchomolunga:

1 >>> isEqual("ChomoLunga","chomolunga")

2 True

Voici un deuxième exemple de décorateur, totalement inutile, mais illustrant bien le fonctionne- ment :

1 def monDecorateur(f) :

2 def _monDecorateur() :

3 print("decorator stuff")

4 f()

5 print("other stuff")

6 return

7 return _monDecorateur

8

10 def cible() :

11 print ("fonction stuff")

et lorsque l’on appelle la fonctioncible(), son comportement a été modifié par le décorateur :

1 >>> cible()

2 decorator stuff

3 fonction stuff

4 other stuff

Comme on le remarque sur cet exemple, dès qu’on applique un décorateur sur une fonction celui- ci prend le contrôle, et peut même complètement ignorer la fonctioncible().

En termes mathématiques, la fonction f décorée par la fonction g est la fonction g◦ f

Documents relatifs