Tutoriel

Python 3.10 en fin de vie : migrer vos applications sur VPS

Développement9 min de lecture7 étapes

Python 3.10 a atteint sa fin de vie en octobre 2026 : plus aucun correctif de sécurité n'est publié pour cette branche. Votre application Django ou FastAPI répond pourtant toujours, et rien ne signale que l'interpréteur est figé. Le risque s'accumule en silence, et la migration paraît plus lourde à chaque mois de retard. Voici une méthode qui ne touche pas à l'existant : un second environnement Python 3.12 à côté du premier, des dépendances verrouillées et testées, puis une bascule réversible en une ligne.

Sommaire· Ce que change la fin de vie de Python 3.101/14
  1. 01Ce que change la fin de vie de Python 3.10
  2. 02Ce que coûte un interpréteur figé
  3. 03Calendrier de support des branches Python
  4. 04Quelle version cible choisir
  5. 05Savoir quel interpréteur sert vraiment la production
  6. 06Prérequis avant de commencer
  7. 07Migrer sans interrompre le service
  8. 08Basculer et revenir en arrière en une ligne
  9. 09Les points de casse à contrôler
  10. 10Liste de contrôle avant la bascule
  11. 11Dépannage : les erreurs qui reviennent
  12. 12Message observé et remède
  13. 13Épingler la cible, pas seulement migrer
  14. 14Faire de la montée de version un geste habituel

Ce que change la fin de vie de Python 3.10

Le guide du développeur Python publie le calendrier de chaque branche. Python 3.10, sortie en octobre 2021, y figure en fin de vie depuis le 1er octobre 2026. Concrètement, la branche ne reçoit plus de correctif, pas même de sécurité : une faille découverte dans l'interpréteur ou dans sa bibliothèque standard restera ouverte.

Votre code continue de tourner et vos tests passent, ce qui rend la situation trompeuse. La fin de vie ne casse rien le jour même. Elle retire le filet pour tous les jours suivants, tandis que les distributions, les images de base et les bibliothèques tierces s'en désintéressent peu à peu.

Ce que coûte un interpréteur figé

  • Failles sans correctif — toute vulnérabilité de l'interpréteur publiée après la fin de vie reste ouverte sur la branche 3.10 ; seule une montée de version la referme.
  • Dépendances qui décrochent — les bibliothèques relèvent tôt ou tard leur version minimale de Python ; une installation neuve finit par résoudre d'anciennes versions, ou par échouer.
  • Images de base figées — une image de conteneur construite sur la branche 3.10 repose sur un interpréteur sans correctif amont, et vos analyses de vulnérabilités le signalent à chaque build.
  • Audits qui coincent — un interpréteur hors support est une ligne rouge dans les revues de sécurité et les questionnaires fournisseurs de vos clients.
  • Migration subie — de 3.10 à 3.12, l'écart couvre deux versions mineures ; plus vous attendez, plus la liste des ruptures s'allonge, et un chantier planifié coûte moins qu'une urgence après incident.

Calendrier de support des branches Python

Faites défiler le tableau

VersionFin de supportLecture pour votre VPS
3.9octobre 2025Hors support depuis plus d'un an : à quitter sans attendre
3.10octobre 2026Hors support depuis le 1er octobre : plus aucun correctif
3.11octobre 2027Palier minimal : il règle le problème du jour, pas celui de l'an prochain
3.12octobre 2028Cible recommandée : deux ans de marge et un écosystème installé
3.13octobre 2029Supportée plus longtemps encore ; à adopter une fois vos dépendances validées
3.14octobre 2030Branche la plus récente de ce tableau, dont la fin de support est la plus lointaine

Quelle version cible choisir

Python 3.12 est la cible que nous recommandons pour une application existante : sa fin de support est planifiée en octobre 2028, soit deux ans de marge, et les frameworks courants la prennent en charge. Python 3.11 est un palier minimal, qui vous ramène devant la même migration en octobre 2027.

Python 3.13 est supportée plus longtemps encore, jusqu'en octobre 2029. Nous ne la jugeons pas inadaptée : elle suppose seulement que chacune de vos dépendances publie ses paquets pour cette version, ce qui se vérifie dans votre environnement de test. Rappel du guide officiel : les dates des branches encore actives sont planifiées et peuvent être ajustées, seules celles de 3.9 et 3.10 sont acquises. Relisez la page avant de figer votre calendrier.

Savoir quel interpréteur sert vraiment la production

python3 --version dans votre shell ne dit pas quel interpréteur sert l'application. Le service peut lancer un environnement virtuel créé il y a des années, un Python compilé à la main, ou une image figée dans un FROM python:3.10.

Recensez chaque source : la ligne ExecStart de l'unité systemd (systemctl cat monapp), le résultat de /srv/monapp/venv/bin/python --version, un grep -rn "FROM python" . sur vos Dockerfiles, le champ requires-python de pyproject.toml et la version utilisée par votre CI. Notez aussi les workers et les tâches planifiées : ils ont souvent leur propre environnement et restent sur l'ancien interpréteur longtemps après le site.

Prérequis avant de commencer

Cette migration ne demande pas de machine particulière, mais un accès complet au serveur et de la place pour deux environnements en parallèle : le second occupe autant de disque que le premier, plus un cache de compilation si une dépendance n'a pas de paquet précompilé.

Il vous faut un fichier de dépendances verrouillé avec des versions exactes, une suite de tests exécutable hors production, une sauvegarde récente de la base de données et l'accès root pour installer, si vos dépendances compilées l'exigent, un compilateur et les en-têtes de développement. Une première passe sur un VPS de test, même éphémère, vaut mieux qu'un essai sur le serveur de production.

Migrer sans interrompre le service

  1. Figer l'existant

    Depuis l'environnement actuel, exportez les versions exactes : /srv/monapp/venv/bin/pip freeze > requirements.lock.txt. Ce fichier décrit précisément ce qui tourne aujourd'hui ; il est votre point de retour. Versionnez-le avant de continuer.

  2. Installer Python 3.12 sans toucher au système

    uv python install 3.12 télécharge un interpréteur 3.12 géré par uv, sans remplacer le python3 de la distribution dont dépendent ses propres outils. Si vous préférez les paquets de votre distribution, installez la branche 3.12 depuis un dépôt qui la fournit et utilisez python3.12 -m venv.

  3. Créer le second environnement à côté du premier

    uv venv --python 3.12 /srv/monapp/venv312 crée l'environnement neuf ; sans uv, python3.12 -m venv /srv/monapp/venv312 fait le même travail. L'ancien continue de servir le trafic : rien n'est modifié. Un environnement virtuel ne se déplace pas, c'est pourquoi le nouveau porte un autre nom.

  4. Réinstaller depuis le fichier verrouillé

    VIRTUAL_ENV=/srv/monapp/venv312 uv pip sync requirements.lock.txt installe exactement les versions listées. Avec pip : /srv/monapp/venv312/bin/pip install -r requirements.lock.txt. Si une version figée n'existe pas pour 3.12 ou refuse de se compiler, l'installation s'arrête ici : c'est le but, vous découvrez la rupture avant la production. Notez chaque paquet à relever.

  5. Rejouer la suite de tests

    Lancez les tests avec le nouvel interpréteur : /srv/monapp/venv312/bin/python -m pytest, ou /srv/monapp/venv312/bin/python manage.py test pour Django, précédé de manage.py check. Lisez le résumé des avertissements de dépréciation : ils annoncent les ruptures de la version suivante. Les tests doivent passer avec les deux interpréteurs avant de continuer.

  6. Monter uniquement ce qui a cassé

    Relevez les paquets en cause, montez-les un par un, puis régénérez le fichier verrouillé depuis le nouvel environnement : /srv/monapp/venv312/bin/pip freeze > requirements.312.txt. Gardez les deux listes, une par interpréteur, le temps de la bascule.

  7. Démarrer l'application en parallèle sur un port local

    Lancez-la avec le nouvel environnement sur un port libre, par exemple /srv/monapp/venv312/bin/gunicorn monapp.wsgi --bind 127.0.0.1:8001 (ou uvicorn pour FastAPI). Envoyez-y des requêtes réelles avec curl : page d'accueil, connexion, une écriture en base. Le trafic public reste sur l'ancien processus ; seul un résultat identique justifie de passer à la bascule.

Basculer et revenir en arrière en une ligne

La bascule ne doit modifier qu'un chemin. Faites pointer l'unité systemd sur un lien plutôt que sur l'environnement : ExecStart=/srv/monapp/venv-actif/bin/gunicorn monapp.wsgi --bind 127.0.0.1:8000. Créez d'abord le lien vers l'état actuel avec ln -sfn /srv/monapp/venv /srv/monapp/venv-actif, puis systemctl daemon-reload et un redémarrage qui ne change rien.

La bascule vers 3.12 devient alors ln -sfn /srv/monapp/venv312 /srv/monapp/venv-actif && systemctl restart monapp, et le retour arrière est la même ligne avec l'ancien chemin. Pour une application en conteneur, le levier est l'image de base : passez de FROM python:3.10-slim à FROM python:3.12-slim, reconstruisez avec docker compose up -d --build et revenez en arrière en rétablissant la ligne précédente.

Dans les deux cas, gardez l'ancien environnement ou l'ancienne image quelques jours, et suivez les journaux avec journalctl -u monapp -f pendant la première heure.

Les points de casse à contrôler

Entre 3.10 et 3.12, la rupture vient rarement de votre code et presque toujours de ce qui l'entoure. Trois familles reviennent : les modules retirés de la bibliothèque standard, les dépendances compilées et la version minimale de vos frameworks. Les notes de version de Python 3.12 listent ce qui disparaît ; lisez-les avec votre fichier verrouillé ouvert à côté.

Liste de contrôle avant la bascule

  • Modules retirés — Python 3.12 supprime distutils, asynchat, asyncore et imp ; grep -rnE "distutils|asyncore|asynchat|import imp" . repère vos usages directs, la liste de vos dépendances révèle les indirects.
  • setuptools n'est plus préinstallé — les environnements créés par venv ne l'embarquent plus en 3.12 ; un paquet qui importe pkg_resources sans le déclarer échoue tant que vous n'avez pas fait pip install setuptools.
  • Paquets précompilés — les dépendances compilées (pilotes de base de données, traitement d'image, cryptographie) doivent publier un paquet pour 3.12 ; pip install --only-binary=:all: -r requirements.lock.txt échoue vite au lieu de lancer une compilation.
  • Versions minimales des frameworks — Django 4.2 ne prend en charge Python 3.12 qu'à partir de la 4.2.8, et Django 5.0 et les suivantes l'acceptent ; pour FastAPI, relisez les classifiers Python de la version exacte que vous épinglez.
  • Avertissements de dépréciation — datetime.utcnow() et datetime.utcfromtimestamp() sont dépréciées en 3.12 ; remplacez-les par datetime.now(datetime.UTC) et datetime.fromtimestamp(ts, datetime.UTC).
  • Bibliothèques système partagées — l'environnement parallèle isole les paquets Python, pas les bibliothèques de l'OS (client PostgreSQL, par exemple) : notez-les, une mise à jour du système peut les changer sous vos pieds.

Dépannage : les erreurs qui reviennent

Ces messages apparaissent dès la première exécution des tests sous Python 3.12. Chacun a une cause connue et un remède court.

Message observé et remède

  • ModuleNotFoundError: No module named 'distutils' — le module a quitté la bibliothèque standard. Installez setuptools dans l'environnement, qui continue d'en fournir une version, puis montez la dépendance fautive.
  • ModuleNotFoundError: No module named 'imp' — imp est retiré, importlib le remplace. Si l'import vient d'un paquet tiers, montez ce paquet vers une version qui ne l'utilise plus.
  • ModuleNotFoundError: No module named 'pkg_resources' — setuptools n'est plus installé d'office dans les environnements venv de 3.12. pip install setuptools rétablit le module en attendant que le paquet fautif s'en passe.
  • DeprecationWarning: datetime.datetime.utcnow() is deprecated — ce n'est pas une erreur mais un signal : remplacez l'appel par un objet conscient du fuseau horaire.
  • Failed building wheel for <paquet> — ce paquet n'a pas de version précompilée pour 3.12 et pip tente de le compiler. Montez-le, ou installez compilateur et en-têtes de développement si la montée est impossible.

Épingler la cible, pas seulement migrer

Profitez de la migration pour fixer l'interpréteur au lieu de le subir : requires-python = ">=3.12" dans pyproject.toml, un tag d'image précis plutôt que python:3, et la version de Python dans la matrice de votre CI. Ajoutez 3.13 à cette matrice en simple observation : vous saurez à l'avance si la prochaine montée sera simple.

Faire de la montée de version un geste habituel

Une branche de Python arrive en fin de vie chaque année, en octobre. La méthode décrite ici (environnement parallèle, fichier verrouillé, tests, bascule réversible) ne dépend d'aucune version précise : elle se rejoue telle quelle pour 3.11 en octobre 2027 et pour 3.12 en octobre 2028, d'après le calendrier actuel.

Si votre application n'est pas encore sur un serveur dont vous maîtrisez l'interpréteur, notre guide de déploiement de Django sur un VPS couvre le premier déploiement. Les guides sur la fin de vie de Node.js et de PHP suivent la même logique pour les autres runtimes d'un parc.

Un serveur où tester la version suivante avant de basculer

Un VPS avec accès root permet de monter un second environnement Python à côté du premier, de valider les tests, puis de basculer. Le choix de l'OS est libre et la capacité se monte à la verticale ; l'option administration VPS prend le relais si vous ne voulez pas tenir le serveur vous-même.

Besoin d'aide ?

Parcourez notre centre d'aide et notre FAQ, ou contactez notre équipe — rappel, WhatsApp ou e-mail. Support en français, anglais et arabe.

Écrire sur WhatsApps'ouvre dans un nouvel onglet