
Le problème : trop d’outils pour gérer Python
Section intitulée « Le problème : trop d’outils pour gérer Python »Si vous avez déjà travaillé sur un projet Python, vous connaissez probablement ces frustrations :
- pip est lent : installer des dépendances prend parfois plusieurs minutes
- Pas de lock file natif : impossible de garantir les mêmes versions entre développeurs sans pip-tools ou poetry
- Jongler entre les outils : pip pour les paquets, virtualenv pour les environnements, pyenv pour les versions Python, pipx pour les outils CLI…
- Conflits de dépendances : le fameux “dependency hell” où deux paquets demandent des versions incompatibles
uv résout tous ces problèmes avec un seul outil, écrit en Rust, qui est 10 à 100 fois plus rapide que pip.
Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »Ce guide vous accompagne pas à pas pour :
- Comprendre pourquoi uv change la donne face à pip et poetry
- Installer uv sur votre système (Linux, macOS, Windows)
- Créer votre premier projet avec une structure propre
- Gérer vos dépendances de façon reproductible avec le lock file
- Exécuter des outils CLI sans polluer votre système (uvx)
- Écrire des scripts autonomes avec leurs dépendances intégrées
- Optimiser vos images Docker avec uv
Pourquoi choisir uv plutôt que pip ou poetry ?
Section intitulée « Pourquoi choisir uv plutôt que pip ou poetry ? »Avant de plonger dans l’installation, comprenons ce qui rend uv différent.
La vitesse : un vrai changement au quotidien
Section intitulée « La vitesse : un vrai changement au quotidien »Quand vous installez des dépendances avec pip, vous attendez. Sur un projet avec beaucoup de dépendances comme Django ou un projet data science avec pandas, numpy et scikit-learn, l’attente peut durer plusieurs minutes.
Avec uv, la même opération prend quelques secondes. Cette différence vient de plusieurs optimisations :
- Résolution parallèle : uv télécharge et analyse plusieurs paquets simultanément
- Cache intelligent : les paquets déjà téléchargés sont réutilisés instantanément
- Code Rust : pas d’interpréteur Python à démarrer, exécution native
Un seul outil au lieu de cinq
Section intitulée « Un seul outil au lieu de cinq »Avant uv, un développeur Python typique devait installer et apprendre plusieurs outils :
- pip pour installer des paquets
- pip-tools ou poetry pour verrouiller les versions
- virtualenv ou venv pour créer des environnements isolés
- pyenv pour gérer plusieurs versions de Python
- pipx pour installer des outils CLI globalement
uv remplace tous ces outils. Vous n’avez qu’une seule commande à apprendre, une seule documentation à consulter, et tout fonctionne ensemble de façon cohérente.
Installation de uv
Section intitulée « Installation de uv »L’installation de uv est simple et ne nécessite pas Python au préalable. C’est un binaire autonome qui fonctionne immédiatement.
Cette méthode fonctionne sur Linux et macOS. Le script détecte votre système et télécharge le bon binaire :
curl -LsSf https://astral.sh/uv/install.sh | shLe script installe uv dans ~/.local/bin. Si ce dossier n’est pas dans votre
PATH, ajoutez cette ligne à votre ~/.bashrc ou ~/.zshrc :
export PATH="$HOME/.local/bin:$PATH"Puis rechargez votre shell avec source ~/.bashrc ou ouvrez un nouveau terminal.
Si vous avez déjà Python et pip installés, vous pouvez utiliser pip pour découvrir uv. C’est pratique pour tester avant de migrer complètement :
pip install uvSi vous rencontrez une erreur de permissions, installez pour votre utilisateur uniquement :
pip install --user uvSi vous utilisez déjà Homebrew pour gérer vos outils, cette méthode garde tout cohérent :
brew install uvHomebrew s’occupe aussi des mises à jour avec brew upgrade uv.
Pour utiliser uv dans une image Docker, copiez simplement le binaire depuis l’image officielle. Pas besoin de l’installer avec un gestionnaire de paquets :
COPY --from=ghcr.io/astral-sh/uv:latest /uv /bin/uvNous verrons plus loin un Dockerfile complet optimisé avec uv.
Vérifier l’installation
Section intitulée « Vérifier l’installation »Une fois installé, vérifiez que uv fonctionne :
uv --versionVous devriez voir quelque chose comme uv 0.5.x. Si vous obtenez
command not found, vérifiez que le dossier d’installation est dans votre PATH.
Gérer plusieurs versions de Python
Section intitulée « Gérer plusieurs versions de Python »Un problème courant en Python : votre projet nécessite Python 3.11, mais votre système a Python 3.9. Ou vous travaillez sur plusieurs projets qui demandent des versions différentes.
Traditionnellement, on utilisait pyenv pour gérer ça. Avec uv, plus besoin d’un outil séparé : uv télécharge et gère les versions Python pour vous.
Voir les versions disponibles
Section intitulée « Voir les versions disponibles »Commencez par lister ce qui est disponible sur votre système et ce que uv peut télécharger :
uv python listLa sortie montre deux types d’entrées :
cpython-3.13.0-linux-x86_64-gnu <download available> # Peut être téléchargécpython-3.12.3-linux-x86_64-gnu /usr/bin/python3.12 # Déjà installécpython-3.11.10-linux-x86_64-gnu <download available> # Peut être téléchargéuv détecte automatiquement les versions Python déjà présentes sur votre système
(installées par le gestionnaire de paquets de votre OS, par exemple). Les
versions marquées <download available> peuvent être installées par uv.
Installer une version spécifique
Section intitulée « Installer une version spécifique »Supposons que votre projet nécessite Python 3.11 et que vous ne l’avez pas. Installez-le simplement :
uv python install 3.11uv télécharge une version précompilée depuis le registre Python. C’est beaucoup plus rapide que de compiler depuis les sources comme le fait pyenv.
Fixer la version pour un projet
Section intitulée « Fixer la version pour un projet »Pour garantir que tous les développeurs utilisent la même version de Python, fixez-la dans le projet :
cd mon-projetuv python pin 3.11Cette commande crée un fichier .python-version contenant simplement 3.11.
Quand quelqu’un clone le projet et exécute uv sync ou uv run, uv utilise
automatiquement cette version (et la télécharge si nécessaire).
C’est un fichier standard reconnu aussi par pyenv et d’autres outils, donc même si vos collègues n’utilisent pas uv, ils sauront quelle version utiliser.
Créer et structurer un projet
Section intitulée « Créer et structurer un projet »Maintenant que uv est installé, créons un vrai projet Python. uv génère une structure de fichiers propre et moderne.
Votre premier projet avec uv
Section intitulée « Votre premier projet avec uv »-
Créer le projet
Placez-vous dans le dossier où vous rangez vos projets et lancez :
Fenêtre de terminal uv init mon-projetcd mon-projetuv crée cette structure :
mon-projet/├── pyproject.toml # Configuration du projet et dépendances├── README.md # Documentation├── .python-version # Version Python à utiliser└── hello.py # Script d'exemple -
Comprendre pyproject.toml
Ce fichier est le cœur de votre projet. Regardons son contenu :
Fenêtre de terminal cat pyproject.toml[project]name = "mon-projet"version = "0.1.0"description = "Add your description here"readme = "README.md"requires-python = ">=3.11"dependencies = []Le fichier
pyproject.tomlest un standard Python (PEP 621) que comprennent pip, poetry, et uv. Vos dépendances seront listées dansdependencies. -
Tester que tout fonctionne
Exécutez le script d’exemple :
Fenêtre de terminal uv run hello.pyVous devriez voir
Hello from mon-projet!. uv a créé automatiquement l’environnement virtuel et exécuté le script dedans.
Quel type de projet choisir ?
Section intitulée « Quel type de projet choisir ? »uv propose trois templates selon ce que vous construisez :
Application simple (par défaut) — pour un script ou un service :
uv init mon-scriptC’est le choix pour la plupart des cas : un outil en ligne de commande, un bot, un service web, etc.
Application packagée — pour une application à distribuer :
uv init --package mon-appCrée une structure avec un dossier src/ et un système de build. Utile si vous
voulez installer votre application comme un paquet ou la publier.
Bibliothèque — pour un package à publier sur PyPI :
uv init --lib ma-libSimilaire à --package, mais configuré pour être importé par d’autres projets
plutôt qu’exécuté directement.
Gérer les dépendances de votre projet
Section intitulée « Gérer les dépendances de votre projet »Les dépendances sont les bibliothèques externes dont votre code a besoin. Par
exemple, si vous faites des requêtes HTTP, vous utiliserez probablement
requests. Si vous faites du web, peut-être flask ou fastapi.
Ajouter une dépendance
Section intitulée « Ajouter une dépendance »Pour ajouter une bibliothèque à votre projet :
uv add requestsQue se passe-t-il ? uv fait trois choses :
- Télécharge le paquet et ses sous-dépendances
- Met à jour
pyproject.tomlavec la nouvelle dépendance - Génère/met à jour
uv.lockavec les versions exactes
Vous verrez requests apparaître dans votre pyproject.toml :
[project]dependencies = [ "requests>=2.32.0",]Dépendances de développement
Section intitulée « Dépendances de développement »Certaines dépendances ne sont utiles que pendant le développement : les outils de test, les linters, les formateurs de code. Elles ne doivent pas être installées en production.
uv les distingue avec l’option --dev :
uv add --dev pytest ruff mypyCes dépendances apparaissent dans une section séparée et ne seront pas
installées quand vous déployez en production avec uv sync --no-dev.
Spécifier une version
Section intitulée « Spécifier une version »Parfois vous avez besoin d’une version précise, par exemple pour éviter un bug ou assurer la compatibilité :
# Au moins la version 2.28uv add 'requests>=2.28'
# Exactement cette versionuv add 'requests==2.28.0'
# Entre deux versionsuv add 'requests>=2.28,<3.0'Supprimer une dépendance
Section intitulée « Supprimer une dépendance »Pour retirer une dépendance devenue inutile :
uv remove requestsuv met à jour pyproject.toml, uv.lock, et désinstalle le paquet de
l’environnement.
Synchroniser l’environnement avec uv sync
Section intitulée « Synchroniser l’environnement avec uv sync »La commande uv sync est fondamentale. Elle garantit que votre environnement
correspond exactement à ce qui est déclaré dans uv.lock :
uv syncConcrètement, uv sync :
- Crée l’environnement virtuel
.venv/s’il n’existe pas - Installe les dépendances aux versions exactes du lock file
- Supprime les paquets qui ne sont plus déclarés
C’est la commande à lancer quand vous clonez un projet ou après un git pull
qui a modifié les dépendances.
Mettre à jour les dépendances
Section intitulée « Mettre à jour les dépendances »# Regénérer le lock fileuv lock --upgrade
# Mettre à jour un paquet spécifiqueuv lock --upgrade-package requestsDépendances conditionnelles
Section intitulée « Dépendances conditionnelles »Pour installer un paquet uniquement sur certaines plateformes :
uv add 'pywin32; sys_platform == "win32"'uv add 'uvloop; sys_platform != "win32"'Exécution de commandes avec uv run
Section intitulée « Exécution de commandes avec uv run »uv run exécute une commande dans l’environnement du projet :
# Exécuter un scriptuv run python script.py
# Lancer un moduleuv run python -m http.server
# Exécuter un outil installé en dépendance devuv run pytestuv run ruff check .Scripts personnalisés
Section intitulée « Scripts personnalisés »Définissez des raccourcis dans pyproject.toml :
[tool.uv.scripts]serve = "python -m http.server"test = "pytest -v"lint = "ruff check ."format = "ruff format ."Puis exécutez-les :
uv run serveuv run testExécuter des outils sans les installer avec uvx
Section intitulée « Exécuter des outils sans les installer avec uvx »Il y a des outils Python que vous utilisez occasionnellement : un formateur de code pour un projet ponctuel, un générateur de documentation, un outil de migration. Les installer globalement encombre votre système et crée des conflits de versions.
uvx résout ce problème. Il télécharge l’outil, l’exécute, et le garde en cache pour la prochaine fois. Rien n’est installé globalement.
Exemple concret
Section intitulée « Exemple concret »Vous voulez formater du code Python avec Black, mais vous ne l’avez pas installé :
uvx black mon_fichier.pyLa première fois, uvx télécharge Black. Les fois suivantes, il utilise le cache et l’exécution est instantanée.
Utiliser une version spécifique
Section intitulée « Utiliser une version spécifique »Vous pouvez demander une version précise avec @ :
uvx ruff@0.5.0 check .C’est utile pour reproduire exactement le comportement d’une CI ou comparer le résultat entre deux versions.
Quand le nom du paquet diffère de la commande
Section intitulée « Quand le nom du paquet diffère de la commande »Parfois le nom du paquet PyPI n’est pas le même que la commande. Par exemple, le
paquet httpie fournit la commande http. Utilisez --from :
uvx --from httpie http GET https://httpbin.org/getOutils courants à utiliser avec uvx
Section intitulée « Outils courants à utiliser avec uvx »Voici quelques outils que vous pouvez lancer sans les installer :
# Formater du codeuvx black .uvx isort .
# Analyser la qualité du codeuvx ruff check .uvx mypy .
# Générer un projet depuis un templateuvx cookiecutter gh:user/mon-template
# Servir de la documentationuvx mkdocs serveScripts avec dépendances inline
Section intitulée « Scripts avec dépendances inline »uv permet de définir les dépendances directement dans un script Python, sans
projet ni pyproject.toml. Idéal pour les scripts autonomes.
#!/usr/bin/env -S uv run# /// script# requires-python = ">=3.11"# dependencies = [# "requests",# "rich",# ]# ///
import requestsfrom rich import print
response = requests.get("https://httpbin.org/get")print(response.json())Exécution
Section intitulée « Exécution »# Rendre exécutablechmod +x mon_script.py
# Exécuter (uv installe les dépendances automatiquement)./mon_script.py# ouuv run mon_script.pyExemple avancé
Section intitulée « Exemple avancé »#!/usr/bin/env -S uv run# /// script# requires-python = ">=3.11"# dependencies = [# "httpx",# "pandas",# "tabulate",# ]# ///
import httpximport pandas as pd
# Récupérer des donnéesresponse = httpx.get("https://api.github.com/repos/astral-sh/uv/releases")releases = response.json()
# Créer un DataFramedf = pd.DataFrame([ {"version": r["tag_name"], "date": r["published_at"][:10]} for r in releases[:5]])
print(df.to_markdown(index=False))Utiliser uv dans Docker
Section intitulée « Utiliser uv dans Docker »Les builds Docker Python sont souvent lents : pip télécharge et installe les dépendances à chaque build, même si rien n’a changé. Avec uv, les builds sont beaucoup plus rapides, et on peut optimiser le cache Docker.
Pourquoi uv change tout pour Docker
Section intitulée « Pourquoi uv change tout pour Docker »Deux avantages majeurs :
- Vitesse : uv installe les dépendances en quelques secondes au lieu de minutes
- Cache Docker optimisé : en copiant
uv.lockavant le code source, Docker réutilise le cache tant que les dépendances ne changent pas
Exemple de Dockerfile optimisé
Section intitulée « Exemple de Dockerfile optimisé »Voici un Dockerfile qui tire parti de ces avantages :
# Étape 1 : ConstructionFROM python:3.12-slim AS builder
# Récupérer le binaire uv depuis l'image officielle# Pas besoin de l'installer avec pip !COPY --from=ghcr.io/astral-sh/uv:latest /uv /bin/uv
WORKDIR /app
# Copier SEULEMENT les fichiers de dépendances d'abord# Astuce : si le code change mais pas les dépendances,# Docker réutilise cette couche en cacheCOPY pyproject.toml uv.lock ./
# Installer les dépendances (sans le code source)# --frozen : échoue si uv.lock n'est pas à jour (sécurité)# --no-dev : pas de dépendances de développement en productionRUN uv sync --frozen --no-dev --no-install-project
# Maintenant copier le code sourceCOPY src ./src
# Installer le projet lui-mêmeRUN uv sync --frozen --no-dev
# Étape 2 : Image finale (plus légère)FROM python:3.12-slim
WORKDIR /app
# Copier uniquement l'environnement virtuel, pas uv ni les sourcesCOPY --from=builder /app/.venv /app/.venv
# Ajouter l'environnement au PATHENV PATH="/app/.venv/bin:$PATH"
CMD ["python", "-m", "mon_app"]Comprendre les options importantes
Section intitulée « Comprendre les options importantes »--frozen fait échouer le build si uv.lock n’est pas synchronisé avec
pyproject.toml. C’est une sécurité : vous savez exactement ce qui est
installé.
--no-dev exclut pytest, ruff et autres outils de développement. Votre
image de production est plus légère et plus sécurisée.
--no-install-project dans la première commande uv sync installe
uniquement les dépendances, pas votre code. Cela maximise l’utilisation du cache
Docker.
Migration depuis pip ou poetry
Section intitulée « Migration depuis pip ou poetry »Depuis pip + requirements.txt
Section intitulée « Depuis pip + requirements.txt »# Initialiser le projetuv init
# Importer les dépendances existantesuv add $(cat requirements.txt | grep -v '^#' | tr '\n' ' ')
# Ou utiliser le mode compatibilité pipuv pip install -r requirements.txtDepuis poetry
Section intitulée « Depuis poetry »# uv lit directement pyproject.toml de poetryuv syncuv comprend le format pyproject.toml de poetry et génère son propre uv.lock.
Construction et distribution
Section intitulée « Construction et distribution »Construire le projet
Section intitulée « Construire le projet »uv buildGénère dans dist/ :
dist/├── mon_projet-0.1.0-py3-none-any.whl└── mon_projet-0.1.0.tar.gzOptions de build
Section intitulée « Options de build »# Distribution source uniquementuv build --sdist
# Wheel uniquementuv build --wheelEspaces de travail (monorepo)
Section intitulée « Espaces de travail (monorepo) »Pour les projets avec plusieurs packages liés, uv supporte les workspaces (inspiré de Cargo).
Configuration
Section intitulée « Configuration »Dans le pyproject.toml racine :
[tool.uv.workspace]members = ["packages/*"]exclude = ["packages/experimental"]Dépendances entre membres
Section intitulée « Dépendances entre membres »[project]dependencies = ["mon-package-interne"]
[tool.uv.sources]mon-package-interne = { workspace = true }Résoudre les problèmes courants
Section intitulée « Résoudre les problèmes courants »”uv: command not found”
Section intitulée « ”uv: command not found” »Le système ne trouve pas uv. Le binaire est probablement installé mais pas dans votre PATH.
Solution : Ajoutez le dossier d’installation au PATH. Si vous avez utilisé le script officiel :
export PATH="$HOME/.local/bin:$PATH"Ajoutez cette ligne à votre ~/.bashrc ou ~/.zshrc pour que ce soit
permanent.
”Lock file is not up to date”
Section intitulée « ”Lock file is not up to date” »Le fichier uv.lock ne correspond plus à pyproject.toml. Quelqu’un a
probablement modifié les dépendances sans régénérer le lock.
Solution : Régénérez le lock file :
uv lockPuis commitez le nouveau uv.lock.
Conflits de versions
Section intitulée « Conflits de versions »Deux dépendances demandent des versions incompatibles d’un même paquet.
Solution : Essayez de mettre à jour toutes les dépendances vers leurs dernières versions compatibles :
uv lock --upgradeSi le conflit persiste, uv affiche quels paquets sont en conflit. Vous devrez peut-être choisir une version différente d’une de vos dépendances directes.
Le cache semble corrompu
Section intitulée « Le cache semble corrompu »Rarement, le cache de uv peut se corrompre (coupure pendant un téléchargement, par exemple).
Solution : Videz le cache et recommencez :
uv cache cleanuv syncCommandes utiles pour diagnostiquer
Section intitulée « Commandes utiles pour diagnostiquer »# Voir la version de uv et où il est installéuv --versionwhich uv
# Voir l'arbre complet des dépendances# (utile pour comprendre d'où vient une sous-dépendance)uv tree
# Lister ce qui est installé dans l'environnementuv pip listÀ retenir
Section intitulée « À retenir »- uv remplace pip, pip-tools, virtualenv, pyenv et pipx en un seul outil
- 10-100x plus rapide que pip grâce à Rust et au cache intelligent
uv syncinstalle exactement ce qui est dansuv.lockuvxexécute des outils CLI sans les installer globalement- Scripts inline avec
# /// scriptpour des scripts autonomes - Docker : copier le binaire depuis
ghcr.io/astral-sh/uv:latest - Migration facile depuis pip ou poetry