Modules

Définition et importation

Un module est un ensemble de définitions d’objets placé dans un fichier (d’extension py). Supposons que l’on souhaite écrire un module pour définir des fonctions permettant de faire des calculs sur le rayonnement du corps noir. Pour ce faire, on enregistre dans un fichier nommé corpsnoir.py le code suivant :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
import numpy

h=6.626e-34 # constante de Planck
c=299792458.0 # vitesse de la lumière
k=1.38e-23 # constante de Boltzmann

def exitance(L,T):
    # L : longueur d'onde en micromètres
    # T : température en Kelvin
    L = L*1e-6
    return 2*numpy.pi*h*c**2/(L**5*(numpy.exp(h*c/(L*k*T))-1))*1e-6

Ce module comporte trois définitions d’objets de type float et une définition de fonction, avec bien sûr des noms associés.

Un module doit être importé dans le script où on veut l’utiliser, ou bien depuis la console. L’importation se fait par l’instruction suivante :

>>> import corpsnoir

Il faut que l’interpréteur de Python trouve le fichier. Il effectue sa recherche dans une liste de chemins, consultable par :

>>> import sys
>>> sys.path

Le répertoire de travail est le premier de la liste. Si le fichier se trouve dans le répertoire de travail, il peut donc être importé. On remarque par ailleurs que le module importe lui-même un autre module, nommé numpy, qui se trouve dans un répertoire de la distribution Python utilisée.

Dès lors que le module est importé, les noms qu’il définit sont accessibles par la syntaxe suivante :

>>> corpsnoir.h
6.626e-34
>>> corpsnoir.exitance(500,1000)
0.00040995221937790315

Les noms définis dans le module ne sont pas dans l’espace de noms global, mais sont accessibles via la notation corpsnoir. (le nom du module suivi d’un point). Il y a ainsi séparation entre l’espace des noms courant et l’espace des noms du module, ce qui est une très bonne chose.

L’inconvénient est l’obligation de placer le nom du module en préfixe de chaque nom. La tâche peut être allégée en introduisant un alias, c’est-à-dire un nom abrégé qui vient remplacer le nom complet, par exemple :

>>> import corpsnoir as cn
>>> cn.h
6.626e-34

Il est possible d’importer des noms dans l’espace de noms courant, mais il faut le faire avec prudence, car cet espace de noms peut contenir déjà des noms identiques à certains noms du module, ce qui viendrait détruire les premiers. Il est donc préférable d’importer dans l’espace de noms courant seulement les noms dont on a besoin :

>>> from corpsnoir import exitance
>>> exitance(500,1000)
0.00040995221937790315

En principe, il vaut mieux éviter ce type d’importation. Il est d’ailleurs possible de faire pire en important dans l’espace de noms courant tous les noms du module :

>>> h = 100
>>> from corpsnoir import *
>>> h
6.626e-34

Comme on le voit sur cet exemple, le nom h dont la déclaration précède l’importation du module et qui pointait vers un entier de valeur 100, est remplacé par la variable définie dans le module, ce qui signifie que le même nom fait finalement référence à un flottant de valeur 6.626e-34. Pour éviter ce genre de désagrément (dont les conséquences peuvent être désastreuses), il est préférable de ne jamais importer de noms dans l’espace de noms courant.

Notons que le contenu d’un module peut être obtenu par la fonction dir (le module doit être déjà importé) :

>>> dir(corpsnoir)
['__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'c', 'exitance', 'h', 'k', 'numpy']

Ce module importe lui-même un module, nommé numpy, dont il a besoin pour faire ses calculs. Cependant, celui-ci serait accessible par la syntaxe corpsnoir.numpy, qui n’a pas de sens puisque le module numpy ne fait pas partie du module corpsnoir.

Exemple : module math

On appelle bibilothèque (library en anglais) un ensemble de modules, mais la notion de bibliothèque ne correspond à rien de précis en Python.

Le logiciel Python est livré avec une bibliothèque appelée bibliothèque standard. Cette bibliothèque est donc présente dans toutes les distributions de Python, même les plus petites.

La bibliothèque standard comporte des modules qui répondent à des besoins très généraux et très variés. Leur liste, ainsi que leur documentation complète, est consultable sur https://docs.python.org/fr/3/library/index.html

Nous nous intéressons en particulier au module math, qui comporte des fonctions mathématiques d’usage courant. Voici par exemple comment se servir de ce module pour calculer un cosinus :

>>> import math
>>> math.pi
3.141592653589793
>>> math.cos(math.pi*0.5)
6.123233995736766e-17

On remarque au passage que le résultat de ce calcul est affecté d’une erreur d’arrondi, puisque le résultat exact est 0.

Paquet

Un paquet (en anglais package) est une organisation hiérarchique de plusieurs modules, qui prend la forme d’une arborescence.

Supposons que l’on souhaite créer un paquet nommé thermo qui contiendrait le module corpsnoir et d’autres modules destinés à faire des calculs dans différents domaines de la thermodynamique. Afin de réaliser un paquet dit classique, nous devons créer l’arborescence de fichiers suivante

thermo/
    __init__.py
    corpsnoir
        __init__.py
    gazparfait
        __init__.py
    fluides
        __init__.py
    etc.

Chaque sous-dossier constitue un module (en fait un sous-module). Le fichier __init__.py contient le code python qui est exécuté lors de l’importation du module. Dans le cas présent, il faut placer le contenu du fichier corpsnoir.py précédent dans le fichier __init__.py du dossier corpsnoir.

L’importation du module se fait de la manière suivante :

>>> import thermo.corpsnoir

ou bien avec un alias :

>>> import thermo.corpsnoir as cn

Le fichier __init__.py du dossier thermo constitue également un module, le module racine du paquet, où on placerait des définitions générales de la thermodynamique, et qui serait importé par :

>>> import thermo

Cependant, cette dernière importation n’importe pas les sous-modules. Ceux-ci doivent être importés explicitement.

Les bibliothèques de grande taille sont généralement organisées sous forme de paquets. Les bibliothèques les plus importantes pour le calcul numérique sont numpy, matplolib et scipy.

On peut par exemple importer numpy :

>>> import numpy

Ce module apporte les fonctions de base pour créer et manipuler des tableaux numériques. Si l’on souhaite en plus générer des tableaux contenant des nombres aléatoires, il faudra faire l’importation suivante :

>>> import numpy.random