Utiliser des scripts Python avec uv et la PEP 723
(cottongeeks.com)- Le gestionnaire de paquets uv et la PEP 723 permettent désormais d’exécuter des scripts Python sans se heurter aux problèmes de dépendances
- La fonctionnalité uvx crée automatiquement des environnements virtuels jetables, ce qui élimine les contraintes de configuration de l’environnement
- En intégrant les métadonnées PEP 723 dans un fichier Python, l’exécution automatique des scripts et la gestion des paquets deviennent plus pratiques
- Un exemple de script exécutable montre qu’il est possible d’implémenter et de déployer rapidement un programme d’extraction de sous-titres YouTube
- Grâce à cela, Python permet désormais lui aussi d’écrire des fichiers exécutables simples et autonomes, ce qui améliore fortement l’utilité des scripts
Vue d’ensemble
- Dans Python, l’inconvénient qui obligeait à reconfigurer l’environnement et à réinstaller les paquets à chaque exécution d’un « script ponctuel » (one-off script) disparaît avec l’arrivée de uv et de la PEP 723
- uv est un gestionnaire de paquets et de projets Python haute performance développé en Rust ; avec sa nouvelle fonctionnalité uvx, il gère de façon très rapide et simple la création d’environnements virtuels jetables, l’installation automatique des paquets et l’association avec la version de Python
Avantages de uv et uvx
- La fonctionnalité uvx fonctionne de manière similaire à npx dans l’écosystème Nodejs, en créant rapidement un environnement d’exécution pour le paquet Python demandé (par exemple
ruff) - Elle s’appuie sur des environnements virtuels jetables mis en cache pour offrir une exécution rapide sans surcoût
- La configuration de l’environnement et l’installation des dépendances se font en une seule ligne de commande, sans que le développeur ait à gérer un environnement séparé
Présentation et usage de la PEP 723
- La PEP 723 définit un standard permettant d’inclure des métadonnées de dépendances et d’environnement en haut d’un script Python
- Exemple : il est possible d’y préciser
requires-python,dependencies, etc. - Les outils externes qui reconnaissent ce format (comme uv) utilisent ces informations écrites dans le fichier de script pour automatiser l’installation, la configuration de l’environnement et l’exécution
Combiner uv et la PEP 723
- Dans un vrai fichier d’exemple Python, on écrit ces métadonnées en tête du fichier, puis l’exécution avec la commande
runde uv installe immédiatement tous les paquets nécessaires, configure la version de Python demandée et lance le code - Le code d’exemple appelle une API sur Internet (la liste des PEP) et affiche le résultat. Tout peut être exécuté en une seule ligne, sans installation de paquets supplémentaire ni configuration d’environnement
Cas pratique : un script de sous-titres YouTube
- Un exemple de script Python est fourni avec un shebang (
#!/usr/bin/env -S uv run --script) et des métadonnées PEP 723 - L’installation automatique de paquets externes comme
youtube-transcript-apiainsi que la configuration automatique de l’environnement virtuel sont prises en charge - L’utilisateur peut fournir comme argument au fichier exécutable (
ytt) une URL ou un ID de vidéo YouTube, puis obtenir immédiatement les sous-titres extraits - Après avoir accordé les droits d’exécution avec
chmod, le script peut être lancé très simplement depuis le terminal
Amélioration de l’expérience développeur et élargissement des possibilités
- Par le passé, même pour de simples scripts, on préférait souvent des langages produisant un binaire autonome comme Go ; désormais, Python offre lui aussi un niveau de simplicité comparable
- La combinaison de uv et de la PEP 723 facilite grandement le partage, le déploiement et l’automatisation de l’exécution des scripts Python
- L’exemple GitHub (
cottongeeks/ytt-mcp) montre qu’il est possible de développer des cas d’usage plus complexes
2 commentaires
uvest incroyablement rapide, c’est vraiment appréciable. En ce moment, je l’utilise partout où c’est possible.Avis Hacker News
Comme l’auteur du billet, ces temps-ci j’ai davantage tendance à me tourner vers des one-off Python cross-platform et des scripts perso plutôt que vers Go, mais je reste insatisfait par le fait que le système de vérification de types de Python soit un chaos absolu ; j’espère que des outils comme ty ou pyrefly amélioreront un peu les choses
On a désormais l’impression que les scripts Python fonctionnent directement sans faire souffrir avec virtualenv Ce serait bien d’avoir une expérience comparable côté shell scripts Le packaging, la gestion des dépendances et la reproductibilité en sont toujours à l’âge de pierre Aujourd’hui encore, la réalité, c’est soit
curl | bashen s’en remettant à la chance, soit un README rempli de 3 dépendances manquantes et de 12 étapes manuelles Nix ? On dirait une option utilisable uniquement pour ceux qui ont déjà transcendé le temps, l’espace et le manuel de Nix Docker ? Si télécharger une distribution Linux pour lancer une seule commandesedvous paraît raisonnable, alors pourquoi pas Il faut vraiment un juste milieu simple, déclaratif et accessible à tousC’est une tendance vraiment excellente, et on a l’impression qu’elle se démocratise de plus en plus Je l’ai découverte au départ sur le blog de simonw, et on peut voir le sujet dans ce billet de blog de simonwillison En mars de cette année, il y a aussi eu une discussion Hacker News autour d’un autre billet de blog J’aimerais que cette tendance reste longtemps en page principale afin que davantage de gens en prennent conscience
Après avoir essayé uv sur de petits projets, l’expérience est vraiment excellente La combinaison
uv runetuv tool run(uvx) rend extrêmement simple l’installation et l’exécution directes, sur une VM, de scripts Python depuis GitHub Pas besoin degit clone, ni de créer ou d’ouvrir unvenv, ni de faire unpip installSurtout, uv est tellement rapide qu’au début j’ai cru qu’il y avait un problème ; en pratique, le résultat est environ 10 fois plus rapide que pip Les outils et la documentation sont encore un peu inachevés, mais c’est déjà largement utilisable vu le niveau d’innovation et d’utilité--helpRust fait aussi évoluer une idée similaire de shell scripts typés en fichier unique C’est d’ailleurs en Rust que j’ai vu ce mode de fonctionnement pour la première fois (prise en charge de l’exécution d’un fichier unique avec gestion des dépendances incluse) J’espère que ce modèle s’implantera dans davantage de langages ; c’est très utile pour se partager des gists ou écrire rapidement de petits outils Voir aussi le document RFC cargo-script
Lorsqu’on utilise
uv run --script, inclure les métadonnées dans le script rend un peu moins pratique le fait d’ouvrir directement un REPL Python depuis le script pour tester des modifications Par exemple, il faut faire quelque chose comme ceci :J’aimerais qu’il existe une manière plus concise Par exemple, l’idéal serait quelque chose comme :
Cela dit, en exécutant en pratique la commande ci-dessous, on peut entrer directement dans l’environnement Python et
venvcorrespondant au script :En revanche, il faut d’abord avoir exécuté le script une fois pour que l’environnement soit créé
--interactiveet l’exposer comme option CLI J’écris souvent de petits CLI basés sur Typer de cette façon Dans un script de dev, j’ai aussi déjà utilisé un flag--sqlpour entrer dans un REPL SQL DuckDBSi vous utilisez conda, il est possible d’activer directement l’environnement dans un wrapper shell pour le script Python Par exemple :
Cela dit, ce n’est pas une approche aussi autonome que le style PEP 723
Après avoir vu les fils HN d’hier et d’aujourd’hui, j’ai décidé d’essayer uv pour la première fois, et j’ai été très impressionné par sa rapidité et la facilité de gestion des dépendances Ce serait encore mieux si la documentation officielle s’améliorait, notamment avec un guide pour passer d’un workflow
requirements.txtà uv La façon de définir la version de Python par projet m’a semblé un peu confuse (définition à deux endroits :.python-versionetpyproject.toml)requires-versiondanspyproject.tomldésigne la plage de versions compatibles garantie, tandis que.python-versionindique la version précise à utiliser pour le développement Avecuv init, les deux semblent identiques au départ, mais avec le temps,requires-versionfinit par indiquer une version minimale prise en charge plus basse que celle de.python-versionrequires-versionentre aussi dans les métadonnées du paquet et influence la résolution des dépendances chez d’autres personnes qui utiliseront le paquet publié Par exemple, si la v1 prend encore en charge une ancienne version de Python mais pas la v2npm updateoudotnet restore, maisvenvcontinue de bien fonctionner sans problème En revanche, avec uv, le changement de plateforme donne l’impression d’être plus complexe et de nécessiter davantage de nettoyage manuelpyproject.tomlsert (indépendamment de uv lui-même) à définir l’environnement nécessaire lorsqu’on partage son code avec des développeurs externes et des utilisateurs Il sert à préciser quel environnement est requis lors de la construction d’un paquet pour PyPI, et la plage de versions est définie pour élargir le plus possible la réutilisabilité du code par d’autres.python-version, lui, ne sert qu’à uv, uniquement lorsqu’il prépare mon environnement de développement Si un environnement a déjà été préparé à l’avance, il n’est pas forcément nécessaire d’en configurer un nouveau uv n’est pas encore le backend de build officiel, mais cette fonctionnalité est en préparation (issue #3957).python-versionest surtout d’assurer la compatibilité avec d’autres outils qui n’ont pas de parseur TOMLJ’avais autrefois envisagé de créer un outil permettant à des scripts Python d’installer eux-mêmes leurs dépendances (avec pour objectif un comportement à la uvx, mais fonctionnant avec seulement Python installé) L’inconvénient, c’est qu’il faut ajouter plusieurs lignes un peu étranges au tout début du script Si ça vous intéresse, c’est publié sur PyPI sous le nom pysolate
Message dans un style Grace Hopper inspiré de COBOL Il faudrait une culture où tous les programmes Python définissent une division ENVIRONMENT afin de documenter clairement l’environnement de compilation et d’exécution, y compris les exigences matérielles et logicielles Une telle structure aurait un effet décisif sur l’amélioration de la portabilité des programmes entre systèmes variés