Vue d'ensemble

Python 3.2, publié le 20 février 2011, est une version riche en nouveautés. Elle introduit argparse pour remplacer optparse, le module concurrent.futures pour simplifier la programmation parallèle, et définit une ABI stable pour les extensions C.

Cette version marque également l'arrivée de functools.lru_cache, un décorateur de mise en cache qui deviendra rapidement indispensable. Avec ces ajouts, Python 3.2 s'impose comme une version mature de la branche 3.x.

Nouveautés majeures

argparse

Le module argparse remplace optparse pour le traitement des arguments en ligne de commande. Il supporte les sous-commandes, la validation de types, les arguments mutuellement exclusifs et la génération automatique de l'aide.

python
import argparse

def creer_parseur():
    """Crée un outil CLI de gestion de fichiers."""
    parseur = argparse.ArgumentParser(
        description="Outil de traitement de données CSV"
    )

    # Argument positionnel obligatoire
    parseur.add_argument("fichier", help="Chemin du fichier CSV")

    # Options avec types et valeurs par défaut
    parseur.add_argument(
        "-d", "--delimiteur",
        default=",",
        help="Délimiteur de colonnes (défaut : virgule)"
    )
    parseur.add_argument(
        "-n", "--nb-lignes",
        type=int,
        default=10,
        help="Nombre de lignes à afficher"
    )

    # Sous-commandes
    sous_parseurs = parseur.add_subparsers(dest="commande")

    # Sous-commande 'resumer'
    sp_resumer = sous_parseurs.add_parser("resumer", help="Affiche un résumé")
    sp_resumer.add_argument(
        "--colonnes",
        nargs="+",
        help="Colonnes à inclure dans le résumé"
    )

    # Sous-commande 'convertir'
    sp_convertir = sous_parseurs.add_parser("convertir", help="Convertit le format")
    sp_convertir.add_argument(
        "--format",
        choices=["json", "xml", "yaml"],
        required=True,
        help="Format de sortie"
    )

    return parseur

# Utilisation :
# python outil.py donnees.csv -n 5 resumer --colonnes nom age
# python outil.py donnees.csv convertir --format json

concurrent.futures

Le module concurrent.futures offre une interface unifiée et de haut niveau pour exécuter des tâches en parallèle, que ce soit avec des threads (ThreadPoolExecutor) ou des processus (ProcessPoolExecutor). Son API basée sur les futures simplifie considérablement la programmation concurrente.

python
from concurrent.futures import ThreadPoolExecutor, ProcessPoolExecutor
import urllib.request
import time

# --- Exemple avec ThreadPoolExecutor : téléchargements parallèles ---

urls = [
    "https://www.python.org",
    "https://pypi.org",
    "https://docs.python.org",
    "https://peps.python.org",
]

def telecharger(url):
    """Télécharge une page et renvoie sa taille."""
    debut = time.time()
    with urllib.request.urlopen(url, timeout=10) as reponse:
        contenu = reponse.read()
    duree = time.time() - debut
    return url, len(contenu), duree

# Téléchargement en parallèle avec 4 threads
with ThreadPoolExecutor(max_workers=4) as executeur:
    resultats = executeur.map(telecharger, urls)

for url, taille, duree in resultats:
    print(f"{url} : {taille} octets en {duree:.2f}s")

# --- Exemple avec ProcessPoolExecutor : calcul intensif ---

def est_premier(n):
    """Vérifie si un nombre est premier."""
    if n < 2:
        return False
    for i in range(2, int(n ** 0.5) + 1):
        if n % i == 0:
            return False
    return True

nombres = [15485863, 15485867, 32452843, 32452867]

with ProcessPoolExecutor() as executeur:
    futurs = {executeur.submit(est_premier, n): n for n in nombres}
    for futur in futurs:
        n = futurs[futur]
        print(f"{n} est premier : {futur.result()}")

ABI stable (PEP 384)

La PEP 384 définit un sous-ensemble stable de l'API C de Python. Les extensions compilées avec cette ABI stable n'ont plus besoin d'être recompilées à chaque nouvelle version mineure de Python. C'est un avantage considérable pour les auteurs de paquets binaires : une seule compilation peut fonctionner sur Python 3.2, 3.3, 3.4 et au-delà.

Pour utiliser l'ABI stable, les auteurs d'extensions doivent définir Py_LIMITED_API lors de la compilation et se limiter aux fonctions documentées comme stables. Les fichiers produits portent l'extension .abi3.so (ou .pyd sous Windows) au lieu du suffixe habituel lié à la version.

functools.lru_cache

Le décorateur functools.lru_cache met en cache les résultats d'une fonction en mémoire, selon une stratégie LRU (Least Recently Used). Il est particulièrement efficace pour les fonctions coûteuses appelées répétitivement avec les mêmes arguments.

python
from functools import lru_cache
import time

# Exemple 1 : calcul récursif avec cache (suite de Fibonacci)
@lru_cache(maxsize=128)
def fibonacci(n):
    """Calcule le n-ième terme de la suite de Fibonacci."""
    if n < 2:
        return n
    return fibonacci(n - 1) + fibonacci(n - 2)

# Sans cache, fibonacci(100) prendrait un temps astronomique
print(fibonacci(100))  # 354224848179261915075
print(fibonacci.cache_info())
# CacheInfo(hits=98, misses=101, maxsize=128, currsize=101)

# Exemple 2 : cache de résultats de conversion
@lru_cache(maxsize=256)
def convertir_temperature(celsius):
    """Convertit Celsius en Fahrenheit avec mise en cache."""
    # Simule un calcul ou un appel coûteux
    return celsius * 9.0 / 5.0 + 32

# Les appels répétés sont instantanés
temperatures_releves = [20, 22, 20, 18, 22, 20, 25, 18]
for temp in temperatures_releves:
    print(f"{temp} C = {convertir_temperature(temp)} F")

print(convertir_temperature.cache_info())
# hits=4 car 20, 22 et 18 sont appelés plusieurs fois

# Vider le cache si nécessaire
convertir_temperature.cache_clear()

Améliorations mineures

  • Les fichiers .pyc sont désormais stockés dans un répertoire __pycache__ avec un nom incluant la version de Python (PEP 3147).
  • Le module logging gagne un dictionnaire de configuration via logging.config.dictConfig().
  • Le module ssl supporte les contextes SSL et la vérification de certificats.
  • Le module html est ajouté avec html.escape().
  • Le format de chaîne str.format_map() est ajouté.

Dépréciations et suppressions

Les changements notables dans cette catégorie :

  • Le module optparse est déprécié au profit de argparse.
  • Les anciennes fonctions de hachage non sécurisées sont dépréciées dans le module hashlib.
  • La randomisation du hachage est introduite (désactivée par défaut, activée par défaut à partir de Python 3.3).
  • Le module platform.dist() est marqué comme obsolète.

Sources