Skip to content

Installer Python 3.15 avec uv : imports paresseux (lazy imports) et compatibilité pandas, PyTorch

Mis à jour le

Installez Python 3.15 en une commande uv, puis vérifiez si numpy, pandas, PyTorch, DuckDB et Polars s'installent vraiment. Testé sur macOS : tableau de compatibilité des wheels, imports paresseux qui font passer le démarrage d'un script de 2.7 s à 0.01 s, les trois cas où lazy import lève une SyntaxError, et le build free-threaded.

La réponse courte : Python 3.15.0 est sorti le 9 octobre 2026. Si vous utilisez uv (opens in a new tab), mettez d'abord uv à jour, puis installez :

uv self update
uv python install 3.15

Créez ensuite un projet de test et essayez vos vraies dépendances avant de migrer quoi que ce soit d'important :

uv init --python 3.15 py315-test
cd py315-test
uv add numpy pandas scikit-learn matplotlib

La pile scientifique de base s'installe aujourd'hui depuis des wheels précompilées. Ce n'est pas le cas de PyTorch ni de TensorFlow. DuckDB se compile depuis les sources. Si votre projet dépend de l'un d'eux, restez sur 3.14 pour l'instant (uv python pin 3.14).

La fonctionnalité qui justifie la mise à jour, ce sont les imports paresseux. Un seul mot-clé, lazy import pandas as pd, a fait passer le chemin --help d'un script de test de 2.7 secondes à 0.01 seconde.

Ce qui a été testé : tout ce qui est marqué « testé » ci-dessous a été exécuté le 11 octobre 2026 sur un Apple M4 Max (macOS) avec uv 0.13.0 et CPython 3.15.0 / 3.15.0t installés via uv python install. Le comportement sous Windows et Linux, l'installateur python.org, pyenv et conda proviennent de la documentation officielle et n'ont pas été testés.

Ce qui change dans 3.15 et que vous allez remarquer

Le changelog est long. Si vous écrivez des scripts de données ou des outils en ligne de commande, voici les cinq changements que vous rencontrerez :

ChangementCe que cela signifie pour vousAction
Imports paresseux (PEP 810)lazy import x reporte le chargement jusqu'à la première utilisationÀ utiliser dans les CLI, les scripts et les applications lentes à démarrer
UTF-8 devient l'encodage par défaut (PEP 686)open("file.txt") lit et écrit désormais en UTF-8 sur tous les systèmesSous Windows, avec des fichiers cp1252 / cp932 / GBK : passez encoding= explicitement
uv 0.13 utilise 3.15 par défautLes nouveaux projets uv sans version épinglée reçoivent 3.15 automatiquementÉpinglez 3.14 là où vos dépendances ne sont pas prêtes
Le build free-threaded obtient une ABI stable (PEP 803)python3.15t exécute les threads en parallèle, mais la plupart des packages ne publient pas encore de wheels ABI stable pour luiAttendez-vous à des compilations depuis les sources sur 3.15t
Types natifs frozendict et sentinel, package profilingNouveaux types natifs et le profileur par échantillonnage TachyonOptionnel ; rien ne casse si vous les ignorez

La liste complète se trouve dans le What's New in Python 3.15 officiel (opens in a new tab). La suite de ce guide couvre les tâches concrètes : installer, vérifier la compatibilité, utiliser les imports paresseux, gérer le changement d'encodage et décider pour le free-threading.

Étape 1 : installer Python 3.15

Avec uv (testé)

Mettez uv à jour avant d'installer. C'est l'erreur la plus facile à commettre cette semaine. Une ancienne version d'uv ne connaît que les builds alpha. Avec le uv 0.9.25 que nous avions déjà, uv python list 3.15 n'affichait que cpython-3.15.0a4. Lancer uv python install 3.15 à ce moment-là aurait installé une alpha, pas la version finale.

uv self update          # needs 0.13.0 or newer
uv --version
uv python install 3.15

uv 0.13.0 a installé le build standard et le build free-threaded en 24.8 secondes :

uv python install 3.15 3.15t
Installed 2 versions in 24.83s
 + cpython-3.15.0+freethreaded-macos-aarch64-none (python3.15t)
 + cpython-3.15.0-macos-aarch64-none (python3.15)

Si vous avez installé uv avec Homebrew, pip ou pipx, uv self update ne fonctionne pas. Mettez-le à jour de la même façon que vous l'avez installé (brew upgrade uv, pipx upgrade uv).

uv 0.13 change aussi la version par défaut. Les notes de version d'uv 0.13.0 (opens in a new tab) indiquent que uv python install sans numéro de version télécharge désormais 3.15. Un nouveau uv venv ou uvx python télécharge 3.15 si aucun Python compatible n'est déjà installé. Les installations existantes restent utilisées. Pour garder un projet sur 3.14, enregistrez-le :

uv python pin 3.14

Cette commande écrit un fichier .python-version, qu'uv lit à chaque exécution dans ce dossier.

Autres méthodes (d'après la documentation officielle, non testées ici)

  • Installateur python.org (Windows, macOS) : téléchargez 3.15.0 sur python.org/downloads (opens in a new tab). D'après les notes de version, l'installateur macOS officiel installe désormais la prise en charge du free-threading par défaut, et les binaires Windows 64 bits utilisent le nouvel interpréteur à appels terminaux (tail-calling).
  • pyenv : pyenv update, puis pyenv install 3.15.0. Attendez que votre version de pyenv affiche 3.15.0.
  • conda : créez un environnement avec python=3.15 une fois que conda-forge l'aura publié. Vérifiez avant de planifier une migration qui en dépend.

Pour une vue générale du changement de version de Python sur chaque système, notre guide pour mettre à jour Python et notre comparatif des gestionnaires de versions Python restent valables. Cette page couvre ce qui est propre à 3.15.

Étape 2 : vérifier que vos packages s'installent

C'est cette étape qui décide si vous pouvez migrer aujourd'hui. Nous avons créé un projet 3.15 vierge, installé une pile data science typique, puis vérifié sur PyPI les packages sur lesquels on nous interroge le plus.

Tableau de compatibilité (testé le 11 octobre 2026)

Package (version)Python 3.15Python 3.15t (free-threaded)Remarques
numpy 2.5.4WheelWheel
pandas 3.0.6WheelWheel
scipy 1.18.1WheelWheel
scikit-learn 1.9.1WheelWheel
matplotlib 3.11.2WheelWheel
pyarrow 26.0.0WheelWheel
polars 2.0.0Wheel (abi3)Compilation depuis les sourcesSon runtime ne publie que des wheels cp310-abi3, inutilisables par Python free-threaded. La compilation Rust a pris 6 min 51 s
ipykernel 9.17.1 (pyzmq, psutil, debugpy)WheelNon testéLes kernels Jupyter fonctionnent sur 3.15
duckdb 1.5.6Compilation depuis les sourcesNon testéLes wheels s'arrêtent à cp314. La compilation C++ a pris environ 2.5 min
pygwalker 0.5.0.1FonctionneNon testéDépend de duckdb, donc hérite de la compilation depuis les sources
torch 2.14.1Impossible à installerImpossible à installerWheels disponibles uniquement de cp310 à cp314 et cp314t
tensorflow 2.21.0Impossible à installerImpossible à installerWheels disponibles uniquement de cp310 à cp313

L'installation de numpy, pandas, scipy, scikit-learn, matplotlib, pyarrow et polars a pris 71 secondes sur 3.15, téléchargement compris, sans aucune compilation. Le même ensemble sur 3.15t a pris 6 minutes 51 secondes, presque entièrement consacrées à la compilation de Polars.

Quand un package n'a pas de wheel, uv vous dit exactement pourquoi. Voici ce que donne PyTorch sur 3.15 :

hint: You require CPython 3.15 (`cp315`), but we only found wheels for `torch`
(v2.14.1) with the following Python ABI tags: `cp310`, `cp311`, `cp312`, `cp313`, `cp314`, `cp314t`

Vérifier votre propre projet en une minute

Inutile d'installer quoi que ce soit pour le savoir. Lancez une simulation (dry run) contre un environnement 3.15 :

uv venv --python 3.15 .venv315
uv pip install --dry-run --python .venv315/bin/python -r requirements.txt

Si la résolution aboutit, tout va bien. Si vous voyez l'indice cp315 ci-dessus, ce package est votre point de blocage.

Une compilation depuis les sources n'est pas un échec, mais elle est lente et nécessite un compilateur (Rust pour Polars, C++ pour DuckDB). En CI, elle peut transformer un job d'une minute en job de dix minutes. Épinglez 3.14 en CI jusqu'à l'arrivée des wheels.

Étape 3 : accélérer le démarrage des scripts avec les imports paresseux

À mon avis, les imports paresseux sont la meilleure raison de passer à 3.15. Le problème qu'ils résolvent est bien connu.

Un script en ligne de commande importe généralement tout en haut du fichier. Même my_tool.py --help paie le coût complet du chargement de pandas, matplotlib et scikit-learn, alors qu'il ne s'en sert jamais.

Avant et après (testé)

La version classique (imports immédiats) :

import sys
import pandas as pd
import matplotlib.pyplot as plt
import sklearn.linear_model
 
if len(sys.argv) > 1 and sys.argv[1] == "--help":
    print("usage: tool [--help] file.csv")
    sys.exit(0)

La version paresseuse ajoute seulement le mot-clé lazy :

import sys
lazy import pandas as pd
lazy import matplotlib.pyplot as plt
lazy from sklearn import linear_model
 
if len(sys.argv) > 1 and sys.argv[1] == "--help":
    print("usage: tool [--help] file.csv")
    sys.exit(0)
 
df = pd.DataFrame({"x": [1, 2, 3], "y": [2, 4, 6]})
model = linear_model.LinearRegression().fit(df[["x"]], df["y"])
print(model.coef_)

Résultats sur notre machine, cinq exécutions de python script.py --help pour chaque version :

VersionTempsLignes dans -X importtime
Imports immédiats2.69 à 2.74 s1,747
lazy import0.01 s27

Le chemin complet fonctionne toujours : la version paresseuse a ajusté la régression et affiché 2.0. pandas se charge à la ligne qui utilise pd pour la première fois.

Vos chiffres absolus seront différents. Dans cet environnement, import sklearn.linear_model prenait à lui seul 2.2 s et import pandas 0.86 s. Le principe reste valable pour toute branche de votre programme qui ne touche pas une bibliothèque lourde.

Voir ce que font les imports paresseux

Un nom paresseux reste un proxy tant que vous ne l'utilisez pas. Vous pouvez le constater :

import sys
lazy import json
 
print(type(globals()["json"]))   # <class 'lazy_import'>
print("json" in sys.modules)     # False
json.dumps(1)
print(type(globals()["json"]), "json" in sys.modules)   # <class 'module'> True

Pour repérer d'abord les imports lents, lancez python -X importtime your_script.py 2> imports.log et triez sur la deuxième colonne.

Trois cas où lazy lève une SyntaxError (testé)

lazy ne fonctionne qu'au niveau du module. Nous avons rencontré ces trois erreurs :

OùMessage d'erreur
Dans une fonctionSyntaxError: lazy import not allowed inside functions
Dans un try / exceptSyntaxError: lazy import not allowed inside try/except blocks
Import étoileSyntaxError: lazy from ... import * is not allowed

La règle sur try/except est la plus gênante. Un code comme try: import ujson as json except ImportError: import json ne peut pas devenir paresseux. Gardez ce repli en import immédiat, ou déplacez-le dans un petit module que vous importez de façon paresseuse.

La documentation officielle précise que les corps de classe et les imports from __future__ ne peuvent pas non plus être paresseux.

Les erreurs apparaissent à la première utilisation

Un module manquant n'échoue plus en haut du fichier :

lazy import not_a_real_module
print("defined ok")          # this prints
not_a_real_module.x          # ModuleNotFoundError is raised here

C'est pratique pour les dépendances optionnelles. Mais une faute de frappe dans un import peut aussi rester cachée jusqu'à l'exécution d'un chemin de code rarement utilisé. Gardez au moins un test qui exerce chaque import paresseux.

Tout rendre paresseux sans modifier le code

Vous pouvez basculer tout le programme en imports paresseux depuis la ligne de commande :

python -X lazy_imports=all my_tool.py --help
# or
PYTHON_LAZY_IMPORTS=all python my_tool.py --help

Notre script d'origine, sans modification, est descendu à 0.01 s de cette façon. Attention toutefois aux modules qui font quelque chose au moment de l'import. Nous avons créé un petit module de plugin qui affiche un message et s'enregistre à l'import. Avec lazy_imports=all, l'enregistrement n'a jamais eu lieu, car le programme n'a jamais touché au nom du module :

normal:   plugin registered / main done
all:      main done

Les bibliothèques qui enregistrent des plugins, des codecs ou des backends matplotlib à l'import peuvent casser de la même manière. Utilisez =all pour mesurer le gain possible, puis ajoutez lazy à la main sur les imports que vous savez sûrs. Pour un contrôle plus fin, la documentation décrit sys.set_lazy_imports_filter().

Prendre en charge 3.14 et 3.15 dans le même fichier

Le mot-clé lazy est une erreur de syntaxe sur 3.14 et les versions antérieures. Si votre code doit tourner sur les deux, utilisez plutôt la liste __lazy_modules__ au niveau du module. Les anciennes versions l'ignorent, et 3.15 traite ces imports comme paresseux :

__lazy_modules__ = ["pandas"]
 
import sys
import pandas as pd          # lazy on 3.15, eager on 3.14
 
print("pandas" in sys.modules)   # False on 3.15 until pd is used

Nous avons vérifié qu'avec ce modèle, pandas restait absent de sys.modules sur 3.15.

Étape 4 : gérer UTF-8 par défaut

Sur 3.15, open() sans argument encoding utilise UTF-8 sur toutes les plateformes. Nous avons confirmé que sys.flags.utf8_mode == 1 par défaut, et 0 avec PYTHONUTF8=0.

Sous macOS et Linux, cela ne change presque rien. Sous Windows, le comportement change pour tout code qui lit des fichiers anciens sans préciser d'encodage : exports CSV d'Excel en cp1252, fichiers japonais Shift-JIS (cp932) ou fichiers chinois GBK. Ces lectures peuvent désormais lever une UnicodeDecodeError ou produire du texte illisible.

La solution est d'être explicite :

import pandas as pd
 
df = pd.read_csv("export.csv", encoding="cp932")      # Japanese Excel export
with open("legacy.txt", encoding="locale") as f:      # old behavior: system locale
    text = f.read()

Pour trouver le code concerné avant de migrer, lancez vos tests sur votre version actuelle de Python avec -X warn_default_encoding. Pour retrouver temporairement l'ancien comportement, définissez PYTHONUTF8=0.

Étape 5 : choisir ou non le build free-threaded (3.15t)

Python free-threaded supprime le GIL, ce qui permet aux threads en pur Python d'utiliser plusieurs cœurs. Nous avons exécuté quatre fois une boucle gourmande en CPU, d'abord séquentiellement, puis sur quatre threads :

BuildSéquentiel4 threadsAccélération
Python 3.150.72 s0.71 s1.0×
Python 3.15t0.65 s0.19 s3.4×

Le GIL est resté désactivé après l'import de numpy, pandas, scikit-learn, polars, matplotlib et pyarrow (sys._is_gil_enabled() renvoyait False).

Utilisez 3.15t si vous exécutez du code pur Python gourmand en CPU dans des threads et que vos dépendances proposent des wheels cp315t. Évitez-le si vous dépendez de Polars, de DuckDB ou de bibliothèques de deep learning. Évitez-le aussi si votre travail lourd tourne déjà dans NumPy ou pandas, qui libèrent le GIL d'eux-mêmes.

Faut-il migrer maintenant ?

Votre situationRecommandation
Scripts, CLI, automatisation avec la pile numpy / pandas / sklearnMigrez. Les imports paresseux sont un vrai gain
Notebooks Jupyter pour l'analyseMigrez dans un nouvel environnement ; gardez l'ancien kernel quelques semaines
Projets PyTorch ou TensorFlowRestez sur 3.14 (uv python pin 3.14)
DuckDB ou Polars sur 3.15t en CIAttendez les wheels, ou acceptez le temps de compilation et un compilateur en CI
Code Windows qui lit des fichiers dans un ancien encodageAjoutez d'abord un encoding= explicite, puis migrez

Utiliser 3.15 dans Jupyter

ipykernel s'installe et fonctionne sur 3.15. Pour enregistrer un kernel 3.15 depuis un projet uv :

uv add ipykernel
uv run python -m ipykernel install --user --name py315 --display-name "Python 3.15"

Si vous travaillez dans des notebooks, RunCell (opens in a new tab) fonctionne comme un agent IA à l'intérieur de Jupyter et voit l'état réel de votre kernel. C'est utile pour vérifier qu'un notebook existant tourne encore sur le nouveau kernel. PyGWalker (opens in a new tab) fonctionne aussi sur 3.15 (testé : pyg.to_html() a rendu un DataFrame), avec la compilation de DuckDB mentionnée plus haut.

Dépannage

SymptômeCauseSolution
uv python install 3.15 installe 3.15.0a4uv est antérieur à 0.13uv self update, ou mise à jour via Homebrew / pipx
No solution found … no wheels with a matching Python ABI tag (cp315)Le package n'a pas encore de wheel 3.15 (torch, tensorflow)uv python pin 3.14 pour ce projet
L'installation bloque plusieurs minutes sur duckdb ou polars-runtimeCompilation depuis les sources faute de wheel compatiblePatientez (il faut un compilateur C++ ou Rust), ou utilisez 3.14 / 3.15 standard au lieu de 3.15t
SyntaxError: lazy import not allowed …lazy dans une fonction, un try ou une classeDéplacez l'import au niveau du module, ou gardez-le immédiat
Un plugin ou un backend ne s'enregistre plus-X lazy_imports=all a sauté un import à effets de bordRetirez =all ; n'utilisez lazy que sur des imports choisis
UnicodeDecodeError sous Windows après la mise à jourUTF-8 est désormais l'encodage par défautPassez encoding="cp1252" / "cp932" / "gbk" ou encoding="locale"
Un nouveau projet uv se retrouve sur 3.15 sans préveniruv 0.13 a changé la version par défautuv python pin 3.14
SyntaxWarning: 'return' in a 'finally' block venant d'une dépendanceLa bibliothèque contient du vieux code signalé par Python récentSans danger ; cela vient de la bibliothèque, pas de votre code

FAQ

Quand Python 3.15 est-il sorti ? Python 3.15.0 est sorti le 9 octobre 2026.

Comment installer Python 3.15 avec uv ? Mettez uv à jour vers 0.13.0 ou plus récent, puis lancez uv python install 3.15. Les anciennes versions d'uv ne connaissent que les builds alpha de 3.15.

pandas fonctionne-t-il sur Python 3.15 ? Oui. pandas 3.0.6 publie des wheels cp315 et cp315t, tout comme numpy, scipy, scikit-learn, matplotlib et pyarrow.

PyTorch prend-il en charge Python 3.15 ? Pas encore. Au 11 octobre 2026, torch 2.14.1 n'a des wheels que jusqu'à cp314 et cp314t, il ne peut donc pas être installé sur 3.15.

Que sont les imports paresseux dans Python 3.15 ? Écrire lazy import module fait créer à Python un proxy léger et ne charge le module qu'à la première utilisation du nom. Cela réduit le temps de démarrage des chemins de code qui n'utilisent jamais le module.

Peut-on utiliser les imports paresseux tout en restant compatible avec Python 3.14 ? Oui. Définissez __lazy_modules__ = ["module_name"] en haut du module. Python 3.15 traite ces imports comme paresseux, et les anciennes versions ignorent la liste.

Comment garder un projet sur Python 3.14 ? Lancez uv python pin 3.14 dans le dossier du projet. La commande écrit un fichier .python-version qu'uv respecte.

Guides associés