Python 3.15 vient de sortir : imports lazy, frozendict et UTF-8 par défaut
Python 3.15 est disponible depuis ce vendredi, et plusieurs de ses nouveautés touchent directement le code que vous écrivez au quotidien, pas seulement les entrailles de l'interpréteur.
Vos imports s'offrent une petite grasse mat'
C'est la nouveauté phare de cette version : le mot-clé lazy (PEP 810) repousse le chargement d'un module jusqu'à sa première utilisation réelle.
Pour rappel, un import classique oblige Python à trouver le fichier, à le lire, à le compiler en bytecode puis à exécuter son contenu. Sur une application aux dépendances touffues, la facture peut atteindre plusieurs secondes au démarrage, même pour des modules qui ne serviront jamais.
lazy import json
lazy from pathlib import Path
Avec ces deux lignes, json et pathlib ne sont réellement chargés qu'au premier appel. Les CLI et les scripts qui importent la moitié de PyPI pour n'en utiliser qu'une poignée sont les premiers à y gagner.
Fini aussi les contorsions pour esquiver un import coûteux en le planquant dans une fonction ou derrière un if TYPE_CHECKING: : tous les imports peuvent rester en haut du fichier, comme le recommande la PEP 8, le guide de style officiel de Python.
Pour du code existant, l'option -X lazy_imports=all (ou la variable d'environnement PYTHON_LAZY_IMPORTS=all) rend tous les imports lazy sans toucher une seule ligne.
Astral, l'éditeur de uv et Ruff dont OpenAI a annoncé le rachat en mars, s'en sert déjà dans une option expérimentale de uv qui accélère jusqu'à 18% la construction des paquets, selon ses propres mesures.
Attention quand même : si un module déclaré en lazy n'arrive pas à se charger, l'exception tombe à sa première utilisation, et non plus au démarrage. Et lazy n'est accepté qu'au niveau du module : dans une fonction, une classe ou un bloc try, c'est la SyntaxError assurée.
frozendict, le dictionnaire immuable
Autre arrivée attendue de longue date, frozendict (PEP 814) rejoint les types natifs : c'est un dictionnaire immuable. Une fois qu'il est créé, impossible d'y ajouter, d'y modifier ou d'y retirer une clé.
De quoi protéger une configuration ou une table de constantes contre une fonction un peu trop zélée. Il sert aussi de valeur par défaut à un argument sans tomber dans le piège classique du {} partagé entre tous les appels.
Comme frozenset, son cousin pour les ensembles présent depuis Python 2.4, il est hachable tant que ses clés et ses valeurs le sont. Il peut donc servir de clé à un autre dictionnaire ou finir dans un set.
Une première proposition avait été rejetée en 2012, faute de cas d'usage convaincants. Quatorze ans plus tard, la donne a changé : Python propose désormais un mode sans GIL (Global Interpreter Lock). Ce verrou global empêche par défaut plusieurs threads d'exécuter du code Python en même temps.
Ce mode et les sous-interpréteurs (plusieurs interpréteurs isolés qui cohabitent dans un même processus, chacun avec son propre GIL) permettent d'exécuter du code Python sur plusieurs cœurs à la fois. Sans eux, il faut répartir le travail entre plusieurs processus, avec le module multiprocessing par exemple.
Un frozendict, que personne ne peut modifier, se partage alors entre threads sans verrou ni risque de conflit.
Ça ne paie pas de mine
Le changement le plus discret de cette version risque pourtant d'en concerner beaucoup : Python utilise désormais l'UTF-8 par défaut, quel que soit l'environnement du système (PEP 686).
Jusqu'ici, un open("fichier.txt") sans paramètre encoding utilisait l'encodage local de la machine, ce qui pouvait réserver son lot de caractères accentués cassés. Un script qui dépendait de l'ancien comportement peut le retrouver en définissant PYTHONUTF8=0 (ou avec l'option -X utf8=0), et encoding="locale" corrige le problème proprement dans le code.
Les compréhensions de liste acceptent aussi l'opérateur (PEP 798) : [x for x in listes] aplatit une liste de listes, là où il fallait passer par itertools.chain() ou par un double for dont personne ne retient jamais l'ordre.
Enfin, les messages d'erreur pensent désormais aux devs qui jonglent entre plusieurs langages : un [1, 2, 3].push(4) vous souffle d'utiliser .append, 'hello'.toUpperCase() renvoie vers .upper et {}.put("a", 1) vous rappelle qu'en Python, on écrit d[k] = v.
Les devs JavaScript et Java se reconnaîtront. 👀
Le JIT passe la seconde
Le compilateur JIT, qui compile à la volée en code machine les portions les plus sollicitées du programme, a été largement remanié depuis son arrivée dans Python 3.13.
Sur la suite de benchmarks pyperformance, il affiche un gain moyen de 7 à 8% sur Linux x86-64 et de 11 à 12% sur les Mac à puce Apple, par rapport à l'interpréteur sans JIT.
Cette moyenne cache de gros écarts d'un benchmark à l'autre : avec le JIT, certains tournent environ 15% moins vite, d'autres plus de deux fois plus vite. Rappelons qu'il reste officiellement expérimental.
Les utilisateurs de Windows, eux, gagnent en vitesse sans rien avoir à activer : les binaires officiels 64 bits passent à l'interpréteur tail-calling apparu avec Python 3.14, une autre façon d'enchaîner les instructions que le compilateur C optimise mieux. Python annonce 15 à 20% de gain moyen sur pyperformance.
Pour savoir où votre propre code passe son temps, la bibliothèque standard accueille aussi Tachyon, un profileur statistique.
Plutôt que d'instrumenter chaque appel de fonction comme cProfile, quitte à ralentir franchement le programme, il relève la pile d'appels jusqu'à un million de fois par seconde, pour un surcoût quasi nul.
Il peut même s'attacher à un processus en cours sans le redémarrer : de quoi ausculter un service qui rame directement en production.
Le Python nouveau est arrivé
Si vos projets tournent encore sous Python 3.10, c'est le bon moment de prévoir une montée de version : la 3.10 est arrivée au bout de ses cinq ans de support le 1er octobre et ne recevra plus aucun correctif de sécurité.
Et pour découvrir les nouveautés autrement qu'en épluchant les notes de version, Barry Warsaw, contributeur historique de CPython, a codé whatsnewt, un jeu d'aventure textuel qui se lance dans le terminal avec uvx --python 3.15 whatsnewt.

Ses dix-huit énigmes se résolvent toutes en écrivant du vrai code Python 3.15, et le jeu cache des easter eggs.
Venant de l'homme qui a droit à son propre easter egg dans CPython (from __future__ import barry_as_FLUFL), le contraire aurait été étonnant.
À propos de l'auteur
Nicolas Lecointre
Fondateur des Joies du Code, je suis l'actualité et la culture des développeurs depuis 2012. Ancien développeur, je me consacre aujourd'hui entièrement au média.
À lire également
Mistral dégaine Large 4, alias Le Chonk, son modèle à 1 000 milliards de paramètres entraîné en Europe
Le Chat a pris du poids — Après des mois de silence assourdissant sur ses grands modèles, Mistral AI a dévoilé le 6 octobre la preview de Mistral Large 4....
Articles similaires
Des neurones humains cultivés en laboratoire jouent à DOOM (oui, vraiment.)
C++26 est officiellement finalisé : la plus grosse mise à jour du langage depuis C++11
Java 26 : Oracle enterre les applets et embarque JavaScript et Python dans la JVM
Des neurones humains cultivés en laboratoire jouent à DOOM (oui, vraiment.)
Mold, le linker ultra-rapide pour Linux, a été réécrit en Rust
C++26 est officiellement finalisé : la plus grosse mise à jour du langage depuis C++11
Java 26 : Oracle enterre les applets et embarque JavaScript et Python dans la JVM
Plus de contenu
Quand on défie le chef de trouver un bug et qu'il casse la prod
Quand le chef me demande si je sais qui est responsable du bug en prod
Quand le chef me demande de lui pondre une estimation en pleine réunion client
Quand on me demande de faire une petite modif dans du code historique
Quand le client n'a pas lu la doc
Quand je corrige un bug sans passer par ChatGPT
Quand le marketing me dit qu'il y a une typo à corriger alors que j'essaie de restaurer la prod
Quand mon projet ne répond plus 30 minutes avant ma présentation
Quand on défie le chef de trouver un bug et qu'il casse la prod
Quand le chef me demande si je sais qui est responsable du bug en prod
Quand le chef me demande de lui pondre une estimation en pleine réunion client
Quand on me demande de faire une petite modif dans du code historique

