6. Modules
**********

Lorsque vous quittez et entrez à nouveau dans l’interpréteur Python,
tout ce que vous avez déclaré dans la session précédente est perdu.
Afin de rédiger des programmes plus longs, vous devez utiliser un
éditeur de texte, préparer votre code dans un fichier et exécuter
Python avec ce fichier en paramètre. Cela s’appelle créer un *script*.
Lorsque votre programme grandit, vous pouvez séparer votre code dans
plusieurs fichiers. Ainsi, il vous est facile de réutiliser des
fonctions écrites pour un programme dans un autre sans avoir à les
copier.

Pour gérer cela, Python vous permet de placer des définitions dans un
fichier et de les utiliser dans un script ou une session interactive.
Un tel fichier est appelé un *module* et les définitions d’un module
peuvent être importées dans un autre module ou dans le module *main*
(qui est le module qui contient vos variables et définitions lors de
l’exécution d’un script au niveau le plus haut ou en mode interactif).

Un module est un fichier contenant des définitions et des
instructions. Son nom de fichier est le nom du module suffixé de
".py". À l’intérieur d’un module, son propre nom est accessible par la
variable "__name__". Par exemple, prenez votre éditeur favori et créez
un fichier "fibo.py" dans le répertoire courant qui contient :

   # Fibonacci numbers module

   def fib(n):    # write Fibonacci series up to n
       a, b = 0, 1
       while b < n:
           print b,
           a, b = b, a+b

   def fib2(n):   # return Fibonacci series up to n
       result = []
       a, b = 0, 1
       while b < n:
           result.append(b)
           a, b = b, a+b
       return result

Maintenant, ouvrez un interpréteur et importez le module en tapant :

   >>> import fibo

Cela n’importe pas les noms des fonctions définies dans "fibo"
directement dans la table des symboles courants mais y ajoute
simplement "fibo". Vous pouvez donc appeler les fonctions *via* le nom
du module :

   >>> fibo.fib(1000)
   1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987
   >>> fibo.fib2(100)
   [1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]
   >>> fibo.__name__
   'fibo'

Si vous avez l’intention d’utiliser souvent une fonction, il est
possible de lui assigner un nom local :

   >>> fib = fibo.fib
   >>> fib(500)
   1 1 2 3 5 8 13 21 34 55 89 144 233 377


6.1. Les modules en détail
==========================

Un module peut contenir aussi bien des instructions que des
déclarations de fonctions. Ces instructions permettent d’initialiser
le module. Elles ne sont exécutées que la *première* fois que le nom
d’un module est trouvé dans un "import" [1] (elles sont aussi
exécutées lorsque le fichier est exécuté en tant que script).

Chaque module possède sa propre table de symboles, utilisée comme
table de symboles globaux par toutes les fonctions définies par le
module. Ainsi l’auteur d’un module peut utiliser des variables
globales dans un module sans se soucier de collisions de noms avec des
variables globales définies par l’utilisateur du module. Cependant, si
vous savez ce que vous faites, vous pouvez modifier une variable
globale d’un module avec la même notation que pour accéder aux
fonctions : "nommodule.nomelement".

Des modules peuvent importer d’autres modules. Il est courant, mais
pas obligatoire, de ranger tous les "import" au début du module (ou du
script). Les noms des modules importés sont insérés dans la table des
symboles globaux du module qui importe.

Il existe une variante de l’instruction "import" qui importe les noms
d’un module directement dans la table de symboles du module qui
l’importe, par exemple :

   >>> from fibo import fib, fib2
   >>> fib(500)
   1 1 2 3 5 8 13 21 34 55 89 144 233 377

Cela n’insère pas le nom du module depuis lequel les définitions sont
récupérées dans la table des symboles locaux (dans cet exemple, "fibo"
n’est pas défini).

Il existe même une variante permettant d’importer tous les noms qu’un
module définit :

   >>> from fibo import *
   >>> fib(500)
   1 1 2 3 5 8 13 21 34 55 89 144 233 377

Importe tous les noms sauf ceux commençant par un tiret bas ("_").

Notez qu’en général, importer "*" d’un module ou d’un paquet est
déconseillé. Souvent, le code devient difficilement lisible. Son
utilisation en mode interactif est acceptée pour gagner quelques
secondes.

If the module name is followed by "as", then the name following "as"
is bound directly to the imported module.

   >>> import fibo as fib
   >>> fib.fib(500)
   0 1 1 2 3 5 8 13 21 34 55 89 144 233 377

This is effectively importing the module in the same way that "import
fibo" will do, with the only difference of it being available as
"fib".

It can also be used when utilising "from" with similar effects:

   >>> from fibo import fib as fibonacci
   >>> fibonacci(500)
   0 1 1 2 3 5 8 13 21 34 55 89 144 233 377

Note: Pour des raisons d’efficience, chaque module n’est importé
  qu’une fois par session de l’interpète.  Si vous changez vos
  modules, vous devrez donc redémarrer votre interprète, ou, si vous
  souhaiter simplement tester un seul module de manière interactive,
  utiliser la fonction "reload()", tel que: "reload(modulename)".


6.1.1. Exécuter des modules comme des scripts
---------------------------------------------

Lorsque vous exécutez un module Python avec :

   python fibo.py <arguments>

le code du module est exécuté comme si vous l’aviez importé mais son
"__name__" vaut ""__main__"". Donc, en ajoutant ces lignes à la fin du
module :

   if __name__ == "__main__":
       import sys
       fib(int(sys.argv[1]))

vous pouvez rendre le fichier utilisable comme script aussi bien que
comme module importable, car le code qui analyse la ligne de commande
n’est lancé que si le module est exécuté comme fichier « main » :

   $ python fibo.py 50
   1 1 2 3 5 8 13 21 34

Si le fichier est importé, le code n’est pas exécuté :

   >>> import fibo
   >>>

C’est typiquement utilisé soit pour proposer une interface utilisateur
pour un module, soit pour lancer les tests sur le module (exécuter le
module en tant que script lance les tests).


6.1.2. Les dossiers de recherche de modules
-------------------------------------------

Lorsqu’un module nommé par exemple "spam" est importé, il est d’abord
recherché parmi les modules natifs puis, s’il n’est pas trouvé,
l’interpréteur cherche un fichier nommé "spam.py" dans une liste de
dossiers donnée par la variable "sys.path". Par défaut, "sys.path" est
initialisée à :

* le dossier contenant le script d’entrée (ou le dossier courant).

* "PYTHONPATH" (une liste de dossiers, utilisant la même syntaxe que
  la variable shell "PATH") ;

* les valeurs par défaut dépendantes de l’installation.

Après leur initialisation, les programmes Python peuvent modifier leur
"sys.path". Le dossier contenant le script courant est placé au début
de la liste des dossiers à rechercher, avant les dossiers de
bibliothèques. Cela signifie qu’un module dans ce dossier, ayant le
même nom qu’un module, sera chargé à sa place. C’est une erreur
typique, à moins que ce ne soit voulu. Voir Modules standards pour
plus d’informations.


6.1.3. Fichiers Python « compilés »
-----------------------------------

Un gain de temps important au démarrage pour les courts programmes
utilisant beaucoup de modules standards, si un fichier "spam.pyc"
existe dans le dossier où "spam.py`est trouvé, il est supposé contenir
une version compilée du module :mod:`spam". La date de modification du
fichier "spam.py" est utilisée pour créer le fichier "spam.pyc", et
stockée dans le fichier "spam.pyc", ainsi le fichier ".pyc" est ignoré
si ces deux dates ne coïncident pas.

Normalement, vous n’avez rien à faire pour créer un fichier
"spam.pyc". Lorsque le fichier "spam.py" est compilé, Python essaye
d’écrire la version compilée dans "spam.pyc". Ce n’est pas une erreur
si cette tentative échoue, et si pour n’importe quelle raison, le
fichier ".pyc" viendrait à ne pas être écrit entièrement, il serait
reconnu comme invalide et ignoré. Le contenu du fichier "spam.pyc" est
indépendant de la plateforme, donc un dossier contenant des modules
Python peut être partagé entre différentes machines de différentes
architectures.

Astuces pour les experts :

* Lorsque l’interpréteur Python est invoqué avec l’option "-O", un
  code optimisé est généré et stocké dans des fichiers en ".pyo".
  L’optimiseur, aujourd’hui, n’aide pas beaucoup, il ne fait que
  supprimer les instructions "assert". Lorsque l’option "-O" est
  utilisée, *tous* les *bytecodes* sont optimisés, les fichiers ".pyc"
  sont ignorés, et les fichier ".py" compilés en un bytecode optimisé.

* Donner deux "-O" à l’interpréteur ("-OO") engendrera un bytecode
  qui pourrait dans de rare cas provoquer un dysfonctionnement du
  programme. Actuellement seulement les chaînes "__doc__" sont retirés
  du bytecode, rendant les ".pyo" plus petits. Puisque certains
  programmes peuvent en avoir besoin, vous ne devriez utiliser cette
  option que si vous savez ce que vous faites.

* Un programme ne s’exécute pas plus vite lorsqu’il est lu depuis un
  ".pyc" ou ".pyo", la seule chose qui est plus rapide est la vitesse
  à laquelle ils sont chargés.

* Lorsqu’un programme est lancé en donnant son nom à une invite de
  commande, le bytecode du script n’est jamais écrit dans un ".pyc" ni
  ".pyo". Cependant son temps de chargement peut être réduit en
  déplaçant la plupart de son code vers un module, et n’utiliser qu’un
  script léger pour importer ce module. Il est aussi possible
  d’exécuter un fichier ".pyc" ou ".pyo" directement depuis l’invite
  de commande.

* Il est possible d’avoir un fichier "spam.pyc" (ou "spam.pyo"
  lorsque "-O" a été utilisée) sans "spam.py" pour un même module.
  Cela permet de distribuer une bibliothèque Python dans un format qui
  est modérément compliqué à rétro-ingénierer.

* Le module "compileall" peut créer des fichiers ".pyc" (ou ".pyo"
  si l’option "-O" est fournie) pour chaque module d’un dossier.


6.2. Modules standards
======================

Python est accompagné d’une bibliothèque de modules standards, décrits
dans la documentation de la Bibliothèque Python, plus loin. Certains
modules sont intégrés dans l’interpréteur, ils exposent des outils qui
ne font pas partie du langage mais qui font tout de même partie de
l’interpréteur, soit pour le côté pratique, soit pour exposer des
outils essentiels tels que l’accès aux appels système. La composition
de ces modules est configurable à la compilation et dépend aussi de la
plateforme cible. Par exemple, le module "winreg" n’est proposé que
sur les systèmes Windows. Un module mérite une attention particulière,
le module "sys", qui est présent dans tous les interpréteurs Python.
Les variables "sys.ps1" et "sys.ps2" définissent les chaînes d’invites
principales et secondaires :

   >>> import sys
   >>> sys.ps1
   '>>> '
   >>> sys.ps2
   '... '
   >>> sys.ps1 = 'C> '
   C> print 'Yuck!'
   Yuck!
   C>

Ces deux variables ne sont définies que si l’interpréteur est en mode
interactif.

La variable "sys.path" est une liste de chaînes qui détermine les
chemins de recherche de modules pour l’interpréteur. Elle est
initialisée à un chemin par défaut pris de la variable d’environnement
"PYTHONPATH" ou d’une valeur par défaut interne si "PYTHONPATH" n’est
pas définie. "sys.path" est modifiable en utilisant les opérations
habituelles des listes :

   >>> import sys
   >>> sys.path.append('/ufs/guido/lib/python')


6.3. La fonction "dir()"
========================

La fonction interne "dir()" est utilisée pour trouver quels noms sont
définis par un module. Elle donne une liste de chaînes classées par
ordre lexicographique :

   >>> import fibo, sys
   >>> dir(fibo)
   ['__name__', 'fib', 'fib2']
   >>> dir(sys)  
   ['__displayhook__', '__doc__', '__excepthook__', '__name__', '__package__',
    '__stderr__', '__stdin__', '__stdout__', '_clear_type_cache',
    '_current_frames', '_getframe', '_mercurial', 'api_version', 'argv',
    'builtin_module_names', 'byteorder', 'call_tracing', 'callstats',
    'copyright', 'displayhook', 'dont_write_bytecode', 'exc_clear', 'exc_info',
    'exc_traceback', 'exc_type', 'exc_value', 'excepthook', 'exec_prefix',
    'executable', 'exit', 'flags', 'float_info', 'float_repr_style',
    'getcheckinterval', 'getdefaultencoding', 'getdlopenflags',
    'getfilesystemencoding', 'getobjects', 'getprofile', 'getrecursionlimit',
    'getrefcount', 'getsizeof', 'gettotalrefcount', 'gettrace', 'hexversion',
    'long_info', 'maxint', 'maxsize', 'maxunicode', 'meta_path', 'modules',
    'path', 'path_hooks', 'path_importer_cache', 'platform', 'prefix', 'ps1',
    'py3kwarning', 'setcheckinterval', 'setdlopenflags', 'setprofile',
    'setrecursionlimit', 'settrace', 'stderr', 'stdin', 'stdout', 'subversion',
    'version', 'version_info', 'warnoptions']

Sans paramètre, "dir()" liste les noms actuellement définis :

   >>> a = [1, 2, 3, 4, 5]
   >>> import fibo
   >>> fib = fibo.fib
   >>> dir()
   ['__builtins__', '__name__', '__package__', 'a', 'fib', 'fibo', 'sys']

Notez qu’elle liste tous les types de noms : les variables, fonctions,
modules, etc.

La fonction "dir()" ne liste pas les noms des fonctions et variables
natives.  Si vous en voulez la liste, ils sont définis dans le module
standard "__builtin__":

   >>> import __builtin__
   >>> dir(__builtin__)  
   ['ArithmeticError', 'AssertionError', 'AttributeError', 'BaseException',
    'BufferError', 'BytesWarning', 'DeprecationWarning', 'EOFError',
    'Ellipsis', 'EnvironmentError', 'Exception', 'False', 'FloatingPointError',
    'FutureWarning', 'GeneratorExit', 'IOError', 'ImportError', 'ImportWarning',
    'IndentationError', 'IndexError', 'KeyError', 'KeyboardInterrupt',
    'LookupError', 'MemoryError', 'NameError', 'None', 'NotImplemented',
    'NotImplementedError', 'OSError', 'OverflowError',
    'PendingDeprecationWarning', 'ReferenceError', 'RuntimeError',
    'RuntimeWarning', 'StandardError', 'StopIteration', 'SyntaxError',
    'SyntaxWarning', 'SystemError', 'SystemExit', 'TabError', 'True',
    'TypeError', 'UnboundLocalError', 'UnicodeDecodeError',
    'UnicodeEncodeError', 'UnicodeError', 'UnicodeTranslateError',
    'UnicodeWarning', 'UserWarning', 'ValueError', 'Warning',
    'ZeroDivisionError', '_', '__debug__', '__doc__', '__import__',
    '__name__', '__package__', 'abs', 'all', 'any', 'apply', 'basestring',
    'bin', 'bool', 'buffer', 'bytearray', 'bytes', 'callable', 'chr',
    'classmethod', 'cmp', 'coerce', 'compile', 'complex', 'copyright',
    'credits', 'delattr', 'dict', 'dir', 'divmod', 'enumerate', 'eval',
    'execfile', 'exit', 'file', 'filter', 'float', 'format', 'frozenset',
    'getattr', 'globals', 'hasattr', 'hash', 'help', 'hex', 'id', 'input',
    'int', 'intern', 'isinstance', 'issubclass', 'iter', 'len', 'license',
    'list', 'locals', 'long', 'map', 'max', 'memoryview', 'min', 'next',
    'object', 'oct', 'open', 'ord', 'pow', 'print', 'property', 'quit',
    'range', 'raw_input', 'reduce', 'reload', 'repr', 'reversed', 'round',
    'set', 'setattr', 'slice', 'sorted', 'staticmethod', 'str', 'sum', 'super',
    'tuple', 'type', 'unichr', 'unicode', 'vars', 'xrange', 'zip']


6.4. Les paquets
================

Packages are a way of structuring Python’s module namespace by using «
dotted module names ».  For example, the module name "A.B" designates
a submodule named "B" in a package named "A".  Just like the use of
modules saves the authors of different modules from having to worry
about each other’s global variable names, the use of dotted module
names saves the authors of multi-module packages like NumPy or Pillow
from having to worry about each other’s module names.

Imaginez que vous voulez construire un ensemble de modules (un «
paquet ») pour gérer uniformément les fichiers contenant du son et des
données sonores. Il existe un grand nombre de formats de fichiers pour
stocker du son (généralement identifiés par leur extension, par
exemple ".wav", ".aiff", ".au"), vous avez donc besoin de créer et
maintenir un nombre croissant de modules pour gérer la conversion
entre tous ces formats. Vous voulez aussi pouvoir appliquer un certain
nombre d’opérations sur ces sons : mixer, ajouter de l’écho, égaliser,
ajouter un effet stéréo artificiel, etc. Donc, en plus des modules de
conversion, vous allez écrire une myriade de modules permettant
d’effectuer ces opérations. Voici une structure possible pour votre
paquet (exprimée sous la forme d’une arborescence de fichiers :

   sound/                          Top-level package
         __init__.py               Initialize the sound package
         formats/                  Subpackage for file format conversions
                 __init__.py
                 wavread.py
                 wavwrite.py
                 aiffread.py
                 aiffwrite.py
                 auread.py
                 auwrite.py
                 ...
         effects/                  Subpackage for sound effects
                 __init__.py
                 echo.py
                 surround.py
                 reverse.py
                 ...
         filters/                  Subpackage for filters
                 __init__.py
                 equalizer.py
                 vocoder.py
                 karaoke.py
                 ...

Lorsqu’il importe des paquets, Python cherche dans chaque dossier de
"sys.path" un sous-dossier du nom du paquet.

Les fichiers "__init__.py" sont nécessaires pour que Python considère
les dossiers comme contenant des paquets, cela évite que des dossiers
ayant des noms courants comme "string" ne masquent des modules qui
auraient été trouvés plus tard dans la recherche des dossiers. Dans le
plus simple des cas, "__init__.py" peut être vide, mais il peut aussi
exécuter du code d’initialisation pour son paquet ou configurer la
variable "__all__" (documentée plus loin).

Les utilisateurs d’un module peuvent importer ses modules
individuellement, par exemple :

   import sound.effects.echo

charge le sous-module "sound.effects.echo". Il doit alors être
référencé par son nom complet.

   sound.effects.echo.echofilter(input, output, delay=0.7, atten=4)

Une autre manière d’importer des sous-modules est :

   from sound.effects import echo

charge aussi le sous-module "echo" et le rend disponible sans avoir à
indiquer le préfixe du paquet. Il peut donc être utilisé comme ceci :

   echo.echofilter(input, output, delay=0.7, atten=4)

Une autre méthode consiste à importer la fonction ou la variable
désirée directement :

   from sound.effects.echo import echofilter

Le sous-module "echo" est toujours chargé mais ici la fonction
"echofilter()" est disponible directement :

   echofilter(input, output, delay=0.7, atten=4)

Notez que lorsque vous utilisez "from package import element",
"element" peut aussi bien être un sous-module, un sous-paquet ou
simplement un nom déclaré dans le paquet (une variable, une fonction
ou une classe). L’instruction "import" cherche en premier si "element"
est défini dans le paquet ; s’il ne l’est pas, elle cherche à charger
un module et, si elle n’en trouve pas, une exception "ImportError" est
levée.

Au contraire, en utilisant la syntaxe "import
element.souselement.soussouselement", chaque "element" sauf le dernier
doit être un paquet. Le dernier "element" peut être un module ou un
paquet, mais ne peut être ni une fonction, ni une classe, ni une
variable définie dans l’élément précédent.


6.4.1. Importer * depuis un paquet
----------------------------------

Qu’arrive-il lorsqu’un utilisateur écrit "from sound.effects import *"
? Idéalement, on pourrait espérer que Python aille chercher tous les
sous-modules du paquet sur le système de fichiers et qu’ils seraient
tous importés. Cela pourrait être long et importer certains sous-
modules pourrait avoir des effets secondaires indésirables ou, du
moins, désirés seulement lorsque le sous-module est importé
explicitement.

La seule solution, pour l’auteur du paquet, est de fournir un index
explicite du contenu du paquet. L’instruction "import" utilise la
convention suivante : si le fichier "__init__.py" du paquet définit
une liste nommée "__all__", cette liste est utilisée comme liste des
noms de modules devant être importés lorsque "from package import *"
est utilisé. Il est de la responsabilité de l’auteur du paquet de
maintenir cette liste à jour lorsque de nouvelles versions du paquet
sont publiées. Un auteur de paquet peut aussi décider de ne pas
autoriser d’importer "*" pour son paquet. Par exemple, le fichier
"sound/effects/__init__.py" peut contenir le code suivant :

   __all__ = ["echo", "surround", "reverse"]

Cela signifie que "from sound.effects import *" importe les trois
sous-modules explicitement désignés du paquet "sound".

Si "__all__" n’est pas définie, l’instruction "from sound.effects
import *" n’importe *pas* tous les sous-modules du paquet
"sound.effects" dans l’espace de noms courant mais s’assure seulement
que le paquet "sound.effects" a été importé (i.e. que tout le code du
fichier "__init__.py" a été exécuté) et importe ensuite les noms
définis dans le paquet. Cela inclut tous les noms définis (et sous-
modules chargés explicitement) par "__init__.py". Sont aussi inclus
tous les sous-modules du paquet ayant été chargés explicitement par
une instruction "import". Typiquement :

   import sound.effects.echo
   import sound.effects.surround
   from sound.effects import *

Dans cet exemple, les modules "echo" et "surround" sont importés dans
l’espace de noms courant lorsque "from...import" est exécuté parce
qu’ils sont définis dans le paquet "sound.effects" (cela fonctionne
aussi lorsque "__all__" est définie).

Although certain modules are designed to export only names that follow
certain patterns when you use "import *", it is still considered bad
practice in production code.

Remember, there is nothing wrong with using "from package import
specific_submodule"!  In fact, this is the recommended notation unless
the importing module needs to use submodules with the same name from
different packages.


6.4.2. Références internes dans un paquet
-----------------------------------------

Les sous modules ont souvent besoin de s’utiliser entre eux. Par
exemple le module "surround" pourrait utiliser le module "echo". Dans
les faits ces références sont si communes que l’instruction clef
"import" regarde d’abord dans le paquet avant de chercher dans les
modules standard. Donc le module "surround" peut simplement utiliser
"import echo" ou "from echo import echofilter". Si le module n’est pas
trouvé dans le paquet courrant (le paquet pour lequel le module actuel
est un sous module), l’instruction "import" cherchera le nom donné en
dehors du paquet.

Lorsque les paquets sont organisés en sous-paquets (comme le paquet
"sound" par exemple), vous pouvez utiliser des imports absolus pour
cibler des paquets voisins. Par exemple, si le module
"sound.filters.vocoder" a besoin du module "echo" du paquet
"sound.effects", il peut utiliser "from sound.effects import echo".

Depuis Python 2.5, en plus des imports relatifs décris plus haut, vous
pouvez écrire des imports relatifs explicites via la syntaxe "form
module import name". Ces imports relatifs explicits utilisent le
préfixe point (".") pour indiquer le paquet courant ou le paquet
parent. Pour le module "surround" par exemple vous pourriez utiliser :

   from . import echo
   from .. import formats
   from ..filters import equalizer

Notez que les imports relatifs, implicites et explicites, sont basés
sur le nom du module courant. Puisque le nom du module principal est
toujours ""__main__"", les modules conçus comme modules principaux
d’une application doivent toujours utiliser des imports absolus.


6.4.3. Paquets dans plusieurs dossiers
--------------------------------------

Les paquets possèdent un attribut supplémentaire, "__path__", qui est
une liste initialisée avant l’exécution du fichier "__init__.py",
contenant le nom de son dossier dans le système de fichiers. Cette
liste peut être modifiée, altérant ainsi les futures recherches de
modules et sous-paquets contenus dans le paquet.

Bien que cette fonctionnalité ne soit que rarement utile, elle peut
servir à élargir la liste des modules trouvés dans un paquet.

-[ Notes ]-

[1] En réalité, la déclaration d’une fonction est elle-même une
    instruction ; son exécution enregistre le nom de la fonction dans
    la table des symboles globaux du module.
