Les nouveautés de Python 3.14

Découvrez toutes les nouveautés de la version 3.14 de Python.

Publié le par Gabriel Trouvé (mis à jour le )
33 minutes

Alors que Python 3.9 arrive en fin de vie, Python 3.14 est officiellement sorti le 7 octobre. Bien que vous puissiez voir la liste de toutes les nouveautés qu'apporte cette version sur le site officiel, nous en avons sélectionné quelques-unes pour vous.

Les templates strings

Une nouveauté qui a largement fait parler d'elle : les t-strings.
Vous connaissez déjà bien les f-strings apparues avec Python 3.6, la référence pour formater les chaînes de caractères. Mais avec la version 3.14, les t-strings font leur apparition.

Avec une syntaxe semblable aux f-strings, vous ne serez pas dépaysés :

nom = "Patrick"
phrase = t"Salut {nom}, comment ça va ?"

print(phrase)
# Template(strings=('Salut ', ', comment ça va ?'), interpolations=(Interpolation('Patrick', 'nom', None, ''),))
PYTHON

Sauf qu'ici, une t-string retourne un objet Template qui sépare le texte statique des variables.

nom = "Patrick"
site = "docstring.fr"

phrase = t"Salut {nom}, comment ça va ? Bienvenue sur {site}"

print(phrase.strings) # ('Salut ', ', comment ça va ? Bienvenue sur ', '')

print(phrase.interpolations) # (Interpolation('Patrick', 'nom', None, ''), Interpolation('docstring.fr', 'site', None, ''))

print(phrase.interpolations[0]) # Interpolation('Patrick', 'nom', None, '')
PYTHON

On retrouve cet objet Template dans from string.templatelib import Template, Interpolation.

L'intérêt des t-strings est de pouvoir manipuler le template avant sa transformation finale.
Ce qui est très pratique pour :

  • Sécuriser des requêtes SQL

  • Générer des logs mieux structurés

  • Utiliser la logique des t-strings dans la construction de frameworks

Une t-string est une structure que l'on peut facilement analyser en accédant aux valeurs interpolées, au texte statique, et au nom des variables.

Prenons un exemple concret d'injection SQL :

def creer_requete_fstring(nom_utilisateur):
  # On colle directement la variable dans la chaîne
  return f"SELECT * FROM users WHERE name = '{nom_utilisateur}'"

 # Un utilisateur malveillant (tentative d'injection SQL)
nom_malveillant = "' OR '1'='1"
requete2 = creer_requete_fstring(nom_malveillant)
print(f"Requête piégée : {requete2}")
# Affiche : SELECT * FROM users WHERE name = '' OR '1'='1'
# La condition est toujours vraie, la requête renverra TOUS les utilisateurs !
PYTHON
Un instant

Ici la requête renverra la liste de tous les utilisateurs, ce qui n'est pas génial 😅.

Utilisons maintenant une t-string :

# Fonction de nettoyage
def creer_requete_sure(template):
    requete_finale = []
    for partie in template:
        if isinstance(partie, str):
            requete_finale.append(partie) # C'est du texte fixe, on garde
        else:
            # C'est une variable, on la nettoie !
            # Ici, on remplace ' par '', ce qui neutralise l'injection SQL
            print(type(partie)) # <class 'string.templatelib.Interpolation'>
            valeur_nettoyee = str(partie.value).replace("'", "''")
            requete_finale.append(f"'{valeur_nettoyee}'")
    return "".join(requete_finale)

def creer_template_tstring(nom_utilisateur):
  # La future requête
  return t"SELECT * FROM users WHERE name = {nom_utilisateur}"

 # Tentons une injection
 nom_malveillant = "' OR '1'='1"
template_requete = creer_template_tstring(nom_malveillant)

# Fonction de nettoyage
requete_securisee = creer_requete_sure(template_requete)
print(f"Requête sécurisée : {requete_securisee}")
# SELECT * FROM users WHERE name = ''' OR ''1''=''1'
PYTHON

Ici la base cherchera un utilisateur dont le nom est littéralement "' OR '1'='1'".

La plupart du temps nous utiliserons les f-strings, mais dans certains cas les t-strings peuvent avoir un réel intérêt !

Messages d'erreur

Qui n'a jamais eu droit à ce message : SyntaxError: invalid syntax ?

Python 3.14 nous simplifie la vie ! Terminé le message d'erreur générique, Python vous donne maintenant des indices :

whil True:
    print("Hello, World!")
    break
SHELL
  File "/Users/gabrieltrouve/Pro/sandbox/main.py", line 1
    whil True:
    ^^^^
SyntaxError: invalid syntax. Did you mean 'while'?
SHELL

Même principe pour les blocs conditionnels :

if True:
    ...
else:
    ...
elif:
    ...
PYTHON
  File "/Users/gabrieltrouve/Pro/sandbox/main.py", line 5
    elif:
    ^^^^
SyntaxError: 'elif' block follows an 'else' block
SHELL

Maintenant on ne sait pas uniquement où est l'erreur, mais pourquoi c'est une erreur. Même si avec l'IA ce type de problème arrive de moins en moins souvent, c'est un excellent moyen de corriger plus vite.

Nous avons vu deux exemples, mais ce principe d'améliorations s'étend à d'autres erreurs de syntaxe.

Coloration syntaxique dans l'interpréteur (REPL)

Dans l'interpréteur de base le code est maintenant coloré.

Coloration syntaxique de Python 3.14

Coloration syntaxique de Python 3.14

Terminé le texte monochrome, bienvenue à la coloration syntaxique en temps réel. Les mots-clés, les chaînes de caractères, les commentaires, chacun sa couleur.

L'évaluation différée des annotations

Un apport de Python 3.14 qui intéressera ceux qui utilisent le type hinting : l'évaluation différée des annotations est activée par défaut.

En effet, Python ne vérifie plus immédiatement ce que signifie un type lorsque vous définissez une fonction. Il le stocke comme du simple texte et ne l'évaluera que plus tard.

Avant Python 3.14, si vous utilisiez un type avant de l'avoir défini, Python levait une erreur :

def create_user(name: str) -> User:
    return User(name)

class User:
    def __init__(self, name: str) -> None:
        self.name = name

user = create_user("Patrick")
print(user.name)
PYTHON
Traceback (most recent call last):
  File "/Users/gabrieltrouve/Pro/sandbox/main.py", line 1, in <module>
    def create_user(name: str) -> User:
                                  ^^^^
NameError: name 'User' is not defined
SHELL

Pour pallier ce problème, il fallait importer annotations de __future__ :

from __future__ import annotations

def create_user(name: str) -> User:
    return User(name)

class User:
    def __init__(self, name: str) -> None:
        self.name = name

user = create_user("Patrick")
print(user.name)
PYTHON

Avec l'évaluation différée par défaut, cet import n'est plus nécessaire. En Python 3.14, ce code est donc tout à fait valide :

def create_user(name: str) -> User:
    return User(name)

class User:
    def __init__(self, name: str) -> None:
        self.name = name

user = create_user("Patrick")
print(user.name)
PYTHON

Avancée sur le GIL

La version sans GIL est désormais officiellement supportée, ce qui ouvre les portes à un vrai parallélisme en Python. La version sans GIL permet à plusieurs threads de s'exécuter en même temps sur différents cœurs.

Mais il faut bien connaître le statut de cette nouveauté :

  • C'est officiel et supporté, CPython s'engage à maintenir cette fonctionnalité

  • Le GIL reste activé par défaut

Il ne suffit pas d'installer la version standard de Python 3.14, mais une version spécifique identifiée par le suffixe "t".

Exemple avec pyenv

Exemple avec pyenv

Cependant, sans le GIL, un code qui n'utilise qu'un seul thread peut s'exécuter de 5 à 10% plus lentement. Aussi, il peut y avoir une incompatibilité avec de nombreuses bibliothèques.

Un compilateur Just-In-Time

Apparu pour la première fois avec Python 3.13, le compilateur Just-In-Time (JIT) était utilisé en compilant soi-même Python. Il n'était donc pas inclus dans les installations standards.

Avec Python 3.14 il devient accessible à tous. En effet, il est disponible dans les versions standards de Python pour Windows et MacOS.

Si l'interpréteur Python classique exécute le code ligne par ligne, le compilateur JIT va plus loin. Il va lire votre code et le traduire en code machine, ce qui est beaucoup plus rapide.

Cependant, il ne faut pas oublier que le statut du JIT est expérimental :

  • Il faut l'activer manuellement en utilisant la variable d'environnement PYTHON_JIT=1

  • Les performances peuvent être variables, il est donc déconseillé de l'utiliser en production

À noter

À savoir que le compilateur JIT et le mode sans GIL sont mutuellement exclusifs.

Les multi-interpreteurs

Vous connaissez certainement threading et multiprocessing ? Ces deux modules permettent d'exécuter plusieurs tâches en même temps :

  • threading utilise des threads qui partagent la même mémoire, mais il existe un risque de conflits d'accès

  • multiprocessing permet de lancer des processus séparés, chacun avec sa propre mémoire, ce qui peut consommer des ressources

Python 3.14 introduit un nouveau module : concurrent.interpreters. L'idée est d'exécuter plusieurs interpréteurs Python dans un même processus, et chaque interpréteur possède sa propre mémoire et son propre état.

Exceptions : une syntaxe plus légère

Jusqu'à présent, pour capturer plusieurs types d'exceptions, il fallait utiliser les parenthèses pour les regrouper dans un tuple.

try:
    with open("config.txt", "r") as f:
        data = f.read()
except (FileNotFoundError, PermissionError):
    print("Le fichier de configuration est introuvable ou inaccessible.")
PYTHON

Si vous n'avez pas besoin de capturer l'exception dans une variable avec le mot-clé as, vous n'avez plus besoin de mettre les parenthèses.

try:
    with open("config.txt", "r") as f:
        data = f.read()
except FileNotFoundError, PermissionError:
    print("Le fichier de configuration est introuvable ou inaccessible.")
PYTHON

Arrivée de Zstandard

Tout d'abord, Python 3.14 réorganise les bibliothèques de compression dans le nouveau module parent compression. Les anciens modules comme gzip ou bz2 sont accessibles via ce nouveau chemin (ex: compression.gzip).

Mais la grande nouveauté, c'est que la bibliothèque standard comprend maintenant Zstandard, un outil de compression moderne. Cet outil est réputé pour sa vitesse de compression et décompression. Son utilisation est très simple :

from compression import zstd

# Des données d'exemple (en bytes)
donnees_originales = b"Le futur de la compression en Python est rapide, tres rapide !" * 10000

# Compression des données
donnees_compressees = zstd.compress(donnees_originales)

print(f"Taille originale : {len(donnees_originales)} octets")
print(f"Taille compressee : {len(donnees_compressees)} octets")

donnees_decompressees = zstd.decompress(donnees_compressees)
print(f"Taille decompressee : {len(donnees_decompressees)} octets")

# Taille originale : 620000 octets
# Taille compressee : 127 octets
# Taille decompressee : 620000 octets
PYTHON

De plus, ce nouveau format est supporté par les modules tarfile, zipfile et shutil de la bibliothèque standard.

Le débogage en production

La dernière version de Python apporte avec elle une interface de débogage externe. En effet, jusqu'à présent, déboguer une application en cours d'exécution était une opération qui risquait de redémarrer l'application. Ce qui dans certains cas, n'est pas acceptable.

Désormais, les débogeurs peuvent s'attacher à un processus Python en cours d'exécution sans arrêter l'application.

Par exemple, imaginons une application tournant avec le PID (Process ID) 5379 que l'on voudrait inspecter pour telle ou telle raison. On voudrait exécuter un script qui s'attache à ce processus pour faire des vérifications :

# Ce script EXTERNE s'exécute dans VOTRE processus
import sys

pid_cible = 5379
chemin_script_debug = "/tmp/mon_code_de_debug.py"

# On demande au processus 5379 d'exécuter mon_code_de_debug.py
sys.remote_exec(pid_cible, chemin_script_debug)
print(f"Le code a été injecté dans le processus {pid_cible}.")
PYTHON

Le processus 5379 exécutera mon_code_de_debug.py au prochain point d'exécution sûr.

Ça ne s'arrête pas là ...

Nous avons vu quelques nouveautés pour cette version de Python 3.14. On ne peut pas TOUT citer, mais vous pouvez vous rendre sur la page de la release note pour consulter l'ensemble des modifications.

Par exemple, il y a eu pas mal d'améliorations au niveau de la bibliothèque standard, notamment pathlib qui se voit doté de nouvelles méthodes comme copy() ou move().

Bravo, tu es prêt à passer à la suite

Rechercher sur le site

Formulaire de contact

Inscris-toi à Docstring

Pour commencer ton apprentissage.

Tu as déjà un compte ? Connecte-toi.