Module et script
Bonjour,
Un fichier python s'appelle un module ? En effet quand on veut faire "nouveau fichier" en fait on clique sur "nouveau module". Pourquoi appeler "module" un "fichier" ? Quel est la différence entre un "module", "un "fichier texte" et un "script" ?
Merci pour vos réponses.
Un fichier python s'appelle un module ? En effet quand on veut faire "nouveau fichier" en fait on clique sur "nouveau module". Pourquoi appeler "module" un "fichier" ? Quel est la différence entre un "module", "un "fichier texte" et un "script" ?
Merci pour vos réponses.
Connectez-vous ou Inscrivez-vous pour répondre.
Réponses
Lorsque tu écris « quand on veut faire "nouveau fichier" en fait on clique sur "nouveau module" », il manque une information cruciale : dans quel programme ? Je devine qu'il s'agit d'un éditeur (de texte qui connaît Python), mais ne puis dire lequel. Python est un langage de programmation ; par ailleurs, on utilise souvent ce nom pour désigner l'interpréteur sans préciser lequel (l'interpréteur officiel est CPython, mais il y en a d'autres). L'éditeur de texte ne vient pas avec, il n'est en tout cas pas imposé ('idle' est juste un exemple d'éditeur écrit... en Python). Chaque utilisateur choisit donc le sien et les utilisateurs qui veulent uniquement exécuter des programmes écrits en Python n'ont pas besoin d'éditeur de texte. Dans un autre éditeur de texte, tu pourrais très bien avoir « Nouveau fichier » pour la même action.
Le fichier est un concept archi-répandu dans les systèmes d'exploitation (OS) pour désigner un espace de stockage généralement durable, accessible aux utilisateurs et presque toujours au sein d'une arborescence (i.e., sauf quand l'OS a été conçu avec les pieds, comme on a pu le voir sur certaines calculatrices). Il n'est pas spécialement lié aux langages de programmation ; mais vu son importance presque partout, une grande partie de ces langages permettent de lire ou écrire dans des fichiers (cependant, il y a assurément des langages spécialisés qui ignorent totalement le concept de fichier, par exemple des mini-langages décrivant des expressions booléennes pour assurer telle ou telle fonction de tel ou tel logiciel).
À l'inverse, le concept de module que l'on rencontre dans Python (rien à voir avec un module en algèbre, évidemment) appartient aux langages de programmation et peut d'ailleurs connaître pas mal de variations d'un language à l'autre. Il y a très souvent une correspondance « 1 module = 1 fichier », d'où les questions que tu te poses, mais en toute généralité, ça ne me paraît pas obligatoire ; par ailleurs, je dirais que le module est quelque chose d'un peu plus abstrait que le fichier.
Le fichier, en gros, c'est un nom auquel est associé un paquet d'octets (un système de fichiers peut donc être vu comme l'implémentation physique d'une sorte de fonction). Pour un module, le fichier est juste un support. Un module est normalement une unité logique de code pour un language de programmation donné (Python, Java...). Il faut stocker ce code quelque part et avoir une correspondance entre un nom (de module) et le support du code. Le plus simple est de stocker le code du module dans un fichier dont le nom est le nom du module (à quelques détails près ; par exemple, en Python, le code d'un module 'machin' est souvent stocké dans un fichier 'machin.py', mais pour les modules Python écrits en C ou en C++, on peut avoir des fichiers .so, .dll ou autres — ça dépend de l'OS). On peut donc utiliser (et on le fait presque toujours) les fichiers comme outils pour implémenter le concept de module, mais le nom d'un module n'est pas, en Python, exactement le nom du fichier correspondant ((a) extension .py à retirer (b) dans le cas des modules Python écrits en C ou C++, on peut avoir par exemple le fichier _hashlib.cpython-37m-x86_64-linux-gnu.so pour le module _hashlib).
[ Il peut donc y avoir quelques nuances entre nom de module et nom de fichier. Ça ne doit pas être très courant, mais rien n'interdit de créer un langage de programmation dans lequel plusieurs fichiers peuvent résulter en un module (c'est déjà le cas avec Python si l'on considère les fichiers source d'un module écrit en C, au lieu du .so/.dll). La situation inverse, avec potentiellement plusieurs modules par fichier, est également envisageable, bien que ça ne doive pas courir les rues. Il faut juste voir si cela va être utile ou va plutôt semer la confusion, ajouter de la complexité pour rien. Exemple : si l'on devait porter Python sur un OS pour calculatrice soit très très limité au niveau des noms de variables (= fichiers dans ce contexte), soit dans lequel un répertoire ne peut pas contenir de sous-répertoire (cas des TI-92 et TI Voyage 200 au moins), on serait probablement obligé de faire quelque chose comme ça pour pouvoir représenter la hiérarchie des modules — et ça ne serait pas de la tarte. ]
Bon, on a vu qu'un fichier est en gros un couple (nom, suite finie d'octets) (idéalement, il faudrait que la suite en question permettent de déterminer simplement, sans recours à des heuristiques, le codage du fichier [ISO 8859-1, UTF-8, etc.] si celui-ci est un fichier texte ; ce point a été négligé depuis les débuts de l'informatique, et à cause de l'existant, c'est la mauvaise conception qui prévaut). Comme je l'ai dit, le module est un concept qui est plus lié au langage de programmation. Puisque tu as parlé de Python, les modules Python :
- fournissent un espace de nommage (namespace, voir ci-dessous).
- déclarent leurs propres dépendances envers d'autres modules (avec la directive 'import') ;
- ne sont normalement chargés qu'une fois au cours d'une exécution donnée de l'interpréteur Python, même si plusieurs directives 'import $m$' sont exécutées pour le même module $m$ ;
- contiennent leur propre déclaration de codage (encoding declaration, optionnelle, UTF-8 si non spécifiée) ;
- sont disposés au sein d'une arborescence (p. ex., 'os.path' est un sous-module de 'os' — ce dernier est donc un package selon la terminologie Python).
Le premier point est hyper important. Quand tu définis une fonction dans un module, ou que tu fais une affectation (telle que sep = 12) au niveau global dans un module, cela n'écrase pas les fonctions ou variables de même nom dans les autres modules (en particulier, os.sep n'est pas modifié ici, sauf évidemment si tu as écrit ce sep = 12 dans le code du module 'os', ce qui serait une drôle d'idée). Dans les langages qui n'ont pas ce concept, on utilise généralement des préfixes pour la plupart des noms de variables ou de fonctions pour éviter les conflits (par exemple, en LaTeX2e, on pourrait utiliser \os@sep et \os@path@join, en Emacs Lisp, os-sep et os-path-join pour ce que Python appelle os.sep et os.path.join et qui peut s'écrire simplement 'sep' dans le code du module os, et 'join' dans celui du module os.path — raccourcis impossibles lorsque toutes les fonctions et variables du langage sont définies dans un unique espace de nommage). La technique du préfixage systématique est nécessaire dans ces cas-là, mais elle produit facilement des noms à rallonge, donc réduit la lisibilité. De plu s, rien ne force son utilisation techniquement en général, il faut donc espérer que les programmeurs sont disciplinés et respectent les conventions, ou alors des conflits peuvent se produire et créer des bugs (si le même nom est utilisé de manière fortuite par deux bouts de code qui s'ignorent l'un l'autre). Bref, on s'en sort, mais c'est moins propre que quand on a le concept de module dans le language.Si tu te renseignes sur le langage C, tu vas voir que c'est un peu plus compliqué. La spécification ne parle pas de module à proprement parler (à ma connaissance), mais le couple (header, translation unit) remplit ce rôle. C++ utilise la même chose mais compte tenu des imperfections, C++20 (pour 2020) est censé venir avec un concept de modules plus pratiques et performants en ce qui concerne le temps de compilation et cette fois-ci, ils utilisent vraiment le terme « module ».
Enfin, un script, c'est un programme écrit dans un langage interprété. Cela veut dire que le code est traduit au fur et à mesure de son exécution en instructions de très bas niveau exécutables par le processeur, au lieu d'être compilé à l'avance. Le code peut donc générer du code et l'exécuter instantanément (ce genre de pratique n'augmente pas forcément la lisibilité, mais c'est une autre histoire). Ceci contraste avec les langages qui nécessitent une étape de compilation comme C et C++, justement. Cette étape traduit le code en fichiers exécutables qui contiennent grosso modo des instructions dans le langage du processeur, pas dans le langage d'origine (C, C++, Ada, Fortran, Rust...). La réalité technique est souvent assez compliquée, mais c'est l'idée essentielle.
Note : Python produit automatiquement des fichiers .pyc ou .pyo lorsqu'on importe un module et que les conditions le permettent (c'est la byte-compilation), mais ces fichiers sont en correspondance directe avec le code, ils sont juste présentés sous une forme que l'interpréteur Python peut lire beaucoup plus vite que le code d'origine. Ils ne sont pas nécessaires et ne changent rien à la nature dynamique de Python. À l'inverse, les fichiers exécutables produits par la compilation de code C ou C++ sont vraiment très différents des fichiers source, ils peuvent faire appel à plein de techniques qui peuvent varier en fonction du compilateur et des options qui lui ont été passées.
Il y a souvent un sous-entendu selon lequel un script = un fichier, mais il me semble que l'on parle aussi de script pour des programmes répartis sur plusieurs fichiers (comme pbuilder, qui est écrit en Bash). Personnellement, je ne fais pas cette distinction. Je n'ai pas non plus de problème à parler de programme écrit en Python plutôt que de script Python (j'utilise plutôt cette dernière expression pour des programmes courts, mais c'est assez arbitraire et la frontière est complètement floue).
-- Schnoebelen, Philippe