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.
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.
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.
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
.pycsont désormais stockés dans un répertoire__pycache__avec un nom incluant la version de Python (PEP 3147). - Le module
logginggagne un dictionnaire de configuration vialogging.config.dictConfig(). - Le module
sslsupporte les contextes SSL et la vérification de certificats. - Le module
htmlest ajouté avechtml.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
optparseest déprécié au profit deargparse. - 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.
