Python est un langage de programmation utilisé dans divers champs d'application. De la création d'interfaces graphiques au développement de serveurs en passant par le scripting d'applications déjà existantes, il est réputé pour sa gratuité, sa portabilité, sa syntaxe simple ainsi que pour sa facilité d'apprentissage. De
Google à la
NASA en passant par
Simple IT, ses fonctionnalités en font aujourd'hui un langage réputé et souvent utilisé par les grandes ou les petites entreprises. Il commence également à percer dans le domaine de l'enseignement, remplaçant le langage de programmation Scheme comme premier langage appris aux étudiants du très fameux
MIT et sera bientôt
intégré dans les cours de mathématiques portant sur l'algorithmique de seconde dans les lycées français.
Le 3 décembre dernier, le langage Python a été séparé officiellement en deux branches :
- Les versions numérotées 2.x.y qui sont rétro-compatibles : cela signifie qu'un programme écrit pour Python 2.4 fonctionne toujours avec Python 2.6 (à quelques exceptions près) ;
- Les versions numérotées 3.x.y qui sont issues d'une refonte totale du langage Python pour le rendre plus logique et moins magique sur certains points. Cependant, un programme écrit pour Python 2.6 ne fonctionnera pas avec Python 3.0.
Depuis la sortie de Python 3.0 (qui a été détaillée dans
une news sur le Site du Zéro), une version dite de
bugfix est sortie le 14 février : Python 3.0.1. Cette version se contente de corriger les bugs de la 3.0 sans rajouter de nouvelles fonctionnalités. Aujourd'hui, la version 3.1 du langage Python vient de sortir : c'est une version mineure, qui reste dans l'esprit de Python 3.0 tout en rajoutant un lot d'améliorations importantes pour les développeurs.
Voyons maintenant plus en détail ce que cette version apporte, puis un petit récapitulatif des discussions et débats importants qui ont eu lieu durant le développement de cette nouvelle version.
Améliorations et nouvelles fonctionnalités
Un des grands thèmes de Python 3.1 a été l'amélioration des performances presque désastreuses de la version 3.0, notamment lors des opérations manipulant des fichiers. Ce fut un des axes majeurs du développement de Python 3.1, mais ce n'est bien entendu pas le seul : voyons plus en détail toutes les nouveautés de Python 3.1.
Réécriture du module io
Le module io
est une nouveauté de Python 3.0 permettant de gérer les entrées-sorties (input-output en anglais, abrégé I/O) d'un programme de manière plus orientée objet que dans les versions 2.x du langage Python. La première implémentation de ce module, dans Python 3.0, était écrite en langage Python, permettant ainsi aux développeurs de tester ce module plus facilement et de comprendre son fonctionnement sans avoir à lire le code de l'interpréteur Python. Cependant, Python a montré ses limitations pour cette tâche au niveau de la vitesse : en effet, les performances étaient de 5 à 8 fois inférieures à celles de Python 2.6, rendant Python 3.0 presque inutilisable pour tout ce qui manipule beaucoup les fichiers.
Dans Python 3.1, il a été décidé d'écrire à nouveau toute la couche I/O de Python 3.0 en C tout en gardant la même interface et le même comportement que la version Python. Cette tâche difficile fut accomplie et l'I/O de Python 3.1 est maintenant plus rapide que celle de Python 2.6 ! Notons tout de même que l'implémentation Python de la couche I/O a été conservée en parallèle dans le module _pyio
pour permettre de vérifier le comportement de la couche C et faciliter l'évolution du module (on peut tester sur la version Python puis recoder en C ensuite).
Pour plus d'informations :
Améliorations des performances globales de l'interpréteur
Python est, à l'instar de Java, un langage semi-compilé. Cela signifie qu'entre un fichier source Python et ce qui sera exécuté, deux étapes ont lieu :
- La compilation du code source qui transforme un langage structuré (Python) en une suite d'instructions appelée bytecode.
- L'exécution du bytecode précédemment obtenu, qui se fait instruction par instruction.
C'est cette deuxième phase qui nous intéresse ici. La méthode la plus simple (et celle qui était en vigueur avant Python 3.1) est celle de la boucle d'évaluation dont le principe est le suivant : tant que l'on n'est pas à la dernière instruction du bytecode, on exécute l'instruction courante et on passe à la suivante. Sous la forme d'un schéma, cette boucle donne ceci :
Dans Python 3.1, une nouvelle option a été ajoutée à la compilation permettant de changer le fonctionnement de l'exécution du bytecode. Appelée --with-computed-gotos, elle passe d'une boucle d'évaluation à une autre méthode qui est nommée l'indirect threading. Son fonctionnement est résumé par le schéma ci-dessous :

Cette technique mise en oeuvre dans Python 3.1 par Antoine Pitrou est plus performante que la boucle d'évaluation pour une raison simple : dans le cas de l'indirect threading, on a un branchement (ou saut) pour chaque instruction du bytecode, alors que dans le cas de la boucle, on a deux branchements pour chaque instruction. Cela a une grande influence sur les performances étant donné que les processeurs actuels essaient en permanence de prédire les branchements pour optimiser la vitesse d'exécution : avoir moins de branchements possibles l'aide donc à mieux prédire et optimiser la suite des événements. Du côté de Python, cela se traduit par une hausse de plus de 20% dans les performances de l'interpréteur, et ce sur n'importe quel programme Python. Cependant, cette option n'est pas utilisée par défaut car certains compilateurs produisent du code peu efficace pour l'indirect threading et ralentissent plus qu'autre chose l'évaluation du bytecode. Ce sera donc le rôle des créateurs de paquets de choisir s'ils souhaitent activer cette optimisation ou non.
Pour plus d'informations :
Un affichage plus esthétique des nombres flottants
Le stockage des nombres flottants (c'est le nom qu'on donne en informatique aux nombres à virgule) en mémoire est un sujet épineux qui entraîne bon nombre de problèmes. En effet, si on prend un nombre comme

qui a un nombre de décimales infini, il est impossible de le représenter exactement sous forme d'octets. Les ordinateurs se limitent donc le plus souvent à 4, 8 ou 12 octets (selon la précision nécessaire pour le programmeur) pour représenter ces nombres. Ainsi, des imprécisions peuvent parfois apparaître et donner lieu à des résultats pour le moins étonnants. Par exemple :
Code : Python Console1
2 | >>> 0.2
0.20000000000000001
|
Ici, on demande à Python d'afficher la représentation sous forme de chaîne de caractères du nombre 0.2, et on se rend compte qu'il trouve effectivement une des représentations possibles de 0.2, mais ce n'est pas la plus esthétique à l'œil. Avec Python 3.1, si on refait la même expérience, on obtient le résultat suivant :
Code : Python ConsoleCe qui est effectivement le résultat attendu. Cette meilleure représentation des nombres flottants vient de l'utilisation d'un algorithme inventé par Guy Steele et John White et implémenté de manière efficace par David Gay qui permet de trouver toutes les représentations d'un nombre flottant et d'en choisir ensuite la plus courte, qui est le plus souvent celle à laquelle on s'attend. Il faut cependant noter que cette amélioration n'augmente pas la précision des nombres flottants mais modifie seulement leur affichage.
Pour plus d'informations :
Une nouvelle structure de données : collections.odict
Python inclut de base une structure de donnée très utile : le dictionnaire (raccourci en dict
, aussi appelé hashtable). C'est un tableau associatif, qui associe donc des clés à des valeurs. Par exemple, ceci est un dictionnaire :
Code : Python1 | {"clé1": "valeur1", "clé2": {"clé3": "valeur3"}}
|
Les dictionnaires en Python sont non ordonnés : c'est-à-dire que si l'on décide de parcourir de bout à bout un dictionnaire, on ne peut pas être sûr de l'ordre dans lequel on va rencontrer les différentes clés. Cependant, on aimerait parfois conserver cet ordre (car on en a besoin dans l'utilisation qu'on fait de la structure de données). Ainsi, Armin Ronacher a proposé le 15 juin 2008 l'inclusion par défaut d'une nouvelle structure de données dans Python, appelée odict
.
Cet ajout a été effectué dans Python 3.1, avec une implémentation de la structure de données en Python dans le module standard collections
. Cependant, un débat a encore lieu concernant odict : en effet, Python propose une fonctionnalité qui s'appelle les keyword args et qui s'utilise de cette façon :
Code : Python1
2
3
4
5
6
7 | def fonction(**kwargs):
# kwargs est un dictionnaire (de type dict) contenant l'association
# nom/valeur des arguments passés à la fonction.
# Exemple d'appel avec des keyword arguments.
# kwargs vaudra {"x": 42, "y": 1337, "test": "salut !"}
fonction(x=42, y=1337, test="salut !")
|
La question est de savoir si kwargs
devrait devenir un odict
ou rester un dict
standard. Il a été décidé que tant que odict
est implémenté en Python, kwargs
restera un dict, mais si un jour une implémentation en C de odict
est presque aussi rapide que celle de dict
, il est tout à fait possible que kwargs
devienne un odict
étant donné que ce changement ne causerait aucun problème de compatibilité.
Pour plus d'informations :
Disparition de contextlib.nested
Les
context managers sont des objets Python un peu spéciaux, dans le sens où ils permettent de simplifier la gestion des exceptions en se fermant automatiquement en cas d'erreur. Par exemple, si une erreur a lieu pendant que vous modifiez un fichier en Python, sans
context manager il y a des chances que votre fichier reste ouvert. Le
tutoriel sur les fonctionnalités avancées de Python (de wgmpgp et Natim) en parle sommairement dans sa dernière partie. Cependant, quand on voulait gérer les erreurs de deux fichiers en même temps avec Python 3.0, la seule solution était la suivante :
Code : Python1
2 | with contextlib.nested(open('fichier1'), open('fichier2')) as (f1, f2):
# Opérations sur f1 et f2
|
Une modification de la syntaxe dans Python 3.1 permet maintenant de simplifier ce code comme ceci :
Code : Python1
2 | with open('fichier1') as f1, open('fichier2') as f2:
# Opérations sur f1 et f2
|
D'autres syntaxes telles que with (open('fichier1'), open('fichier2')) as (f1, f2):
ont également été proposées mais finalement refusées au profit de celle qui est en place dans Python 3.1.
Pour plus d'informations :
Cycle de développement de cette version
Voyons maintenant en détail comment cette version de Python a été développée en observant la chronologie des événements importants s'étant déroulés entre la sortie de Python 3.0 et celle de Python 3.1.
27 Janvier 2009 : lancement du projet Snakebite
Snakebite est un réseau de 37 serveurs sous différentes architectures et différents systèmes d'exploitation qui a vocation à servir d'aide aux développeurs pour maintenir un interpréteur Python fonctionnant sur le plus de machines possibles. Soutenu par différentes entreprises comme Microsoft, Sun, Google, HP ou MSU qui ont données des licences ou du matériel pour le projet, il fera fonctionner différents
buildbots (ce sont des programmes qui récupèrent les dernières versions de différents projets, les compilent, les testent automatiquement et renvoient les résultats) pour les projets en rapport avec Python en priorité (PyPy, Jython ou IronPython sont par exemple cités), et peut-être d'autres ensuite. En résumé, même si ce projet lancé par Trent Nelson n'est pour le moment pas encore en fonctionnement, c'est probablement l'avenir du développement de nombreux projets Python-related.
Pour plus d'informations :
8 février 2009 : annonce de la chronologie des versions non finales
La
PEP 375 a été publiée par le
release manager (celui qui s'occupe d'annoncer les sorties des versions et décide des priorités des nouvelles fonctionnalités en fonction des dates de sorties) de la version 3.1, Benjamin Peterson, et annonce deux versions alpha, une version beta puis deux versions
release candidate avant la sortie finale le 27 Juin.
13 février 2009 : début du débat sur yield from
La PEP 380 a été une des améliorations de Python les plus débattues durant le cycle de développement de Python 3.1. Cette proposition d'amélioration permet de renvoyer les valeurs successives d'un sous-générateur dans un générateur : en très simplifié, yield from gen
est équivalent à for x in gen: yield x
. Cependant, l'implémentation de cette fonctionnalité a nécessité de nombreuses modifications dans la sémantique des générateurs avec l'introduction de nouvelles exceptions comme GeneratorExit
et n'a donc pas été retenue pour Python 3.1. Elle sera cependant probablement intégrée dans Python 2.7 et Python 3.2.
Pour plus d'informations :
23 mars 2009 : début du débat sur les systèmes de packaging de Python
Partie à l'origine d'une demande d'inclusion d'un module à la bibliothèque standard, cette discussion a été un des axes majeurs des PyCon US (une semaine de conférences sur le langage Python) notamment lors de l'habituel language summit où les plus gros contributeurs à Python se réunissent pour parler de divers sujets préparés à l'avance. En effet, Python ne propose en standard aucun moyen simple d'installer ou de désinstaller des modules externes depuis internet à la manière d'un gestionnaire de paquet, ce qui pose problème lorsque l'on souhaite utiliser une version plus à jour que celle de la distribution Linux qu'on utilise. Il existe bien différentes alternatives comme setuptools ou pip (qui sont toutes deux matures et utilisent les mêmes sources pour installer les paquets), mais elles ne se sont que très peu démocratisées du fait de leur absence de la bibliothèque standard de Python. La solution choisie a été d'améliorer l'outil préinstallé avec Python, distutils, pour lui faire supporter toutes les fonctionnalités de ses concurrents. Cependant c'est un travail de longue haleine qui ne prendra sûrement pas forme avant un moment.
Pour plus d'informations :
28 mars 2009 : Unladen Swallow
Tirant son nom de
la question posée par le vieux de la scène 24 dans
Sacré Graal ! des Monty Python, le projet Unladen Swallow vise à améliorer les performances de Python d'un facteur 5 ou plus, et ce en utilisant ce que l'on appelle un
Just in Time compiler, qui transforme le bytecode Python en code machine pendant l'exécution, le rendant directement exécutable par le processeur de l'ordinateur. Se basant sur le projet LLVM (Low-Level Virtual Machine) qui travaille sur la réalisation d'un JIT multiplateforme et réutilisable, les ingénieurs de Google ont lancés ce projet fin mars 2009 et ont dors et déjà une version apportant des hausses de performances de l'ordre de +25% par rapport à l'intepréteur Python classique.
Pour plus d'informations :
30 mars 2009 : choix du DVCS qui remplacera Subversion
La discussion enclenchée le 7 novembre 2008 sur le changement de
VCS de Python pour passer de Subversion à un
DVCS est arrivée à son terme le 30 mars 2009 quand Guido van Rossum, créateur de Python, a tranché sur son choix de système pour la suite du développement de Python. Le choix ayant à la base été réduit à trois systèmes (Git, Mercurial et Bazaar) fut tout de même très difficile du fait des différents avantages et inconvénients de chacun de ces programmes, qui pourraient influer directement sur la qualité du développement de Python. C'est finalement
Mercurial qui a été choisi pour remplir cette tâche, pour la simple et bonne raison qu'il est un des plus simple à prendre en main pour un développeur habitué à Subversion et que Bazaar est trop lent pour gérer de gros projets comme l'interpréteur Python. La transition à Mercurial n'a pas encore totalement été effectuée et devrait se terminer fin 2009 par le retrait du dépôt public Subversion.
Pour plus d'informations :
1er avril 2009 : démission du BDFL
Pour la traditionnelle blague du premier avril, le BDFL (Benevolent Dictator for Life, Dictateur Bienveillant à Vie, surnom de Guido van Rossum, le créateur de Python) a décidé d'annoncer qu'il prenait sa retraite après 20 ans de développement relatif à Python, et qu'il nommait Barry Warsaw (un des core-developers de Python) pour le remplacer à cette tâche. Son titre fut modifié de BDFL à BDEVIL (Benevolent Dictator Emeritus Vacationing Indefinitely from the Language), et Barry Warsaw se donna le nouveau titre de FLUFL (Friendly Language Uncle For Life), insistant pour être appelé « Uncle Barry » par la suite. Tout cela s'étant déroulé pendant les PyCon US où la majorité des acteurs du développement de Python étaient rassemblés, il va sans dire que ce fut un joli coup.
Pour plus d'informations :
1er juin 2009 : retrait de ipaddr dans Python 3.1
ipaddr
est un module Python créé par des ingénieurs de Google pour faciliter les opérations sur les adresses IP, et dont l'introduction dans la bibliothèque standard de Python (stdlib) avait été décidée le 3 mai dernier. Cependant, après la sortie de la première version RC, un débat est apparu sur le modèle qu'utilisait cette bibliothèque pour représenter les adresses IP et les réseaux, qui ne plaisait pas à certains développeurs (mais que d'autres trouvaient naturel). Son retrait a été demandé à cause de ce consensus, mais retirer un module de la bibliothèque standard n'est normalement pas réalisable après la sortie de la première release candidate qui est sensée être compatible avec la version finale. Ainsi, le débat s'est peu à peu transformé pour discuter plus précisément de la cohésion des décisions prises par les core-developers de Python et les tests qui sont effectués avant l'introduction d'une nouvelle fonctionnalité. Pour finir, le BDFL a tranché en demandant le retrait de la bibliothèque de la stdlib, citant comme argument que « si quelqu'un souhaite vraiment l'utiliser avec Python 3.1, il a toujours le choix d'installer le module externe comme avant », mais ce fut une décision exceptionnelle qui n'aurait normalement pas du être prise.
Pour plus d'informations :
Conclusion
Python est un langage de programmation qui se démocratise de plus en plus, que ce soit chez les amateurs que dans les grandes entreprises. Cette version 3.1 rend l'interpréteur plus rapide et y rajoute plusieurs fonctionnalités manquantes et demandées par les utilisateurs. Cependant, peu de bibliothèques lourdes telles que NumPy (pour le calcul scientifique), la PIL (pour traiter des images) ou SQLAlchemy (pour utiliser des bases de données facilement) sont déjà disponibles pour les versions 3.x de Python, rendant son utilisation plus rare que celle des version 2.x. Mais cette tendance tend à s'inverser, et de grosses bibliothèques telles que PyQt fournissent déjà une version utilisable pour Python 3.0. Ce n'est donc à priori qu'une question de temps et de motivation des développeurs pour que les autres s'y mettent et que Python 3.x remplace définitivement Python 2.x dans l'avenir du langage.
Références