Use Cases (Mis à jour: 02/06/2026)

Python avec Claude Code : guide uv, pytest, Ruff et FastAPI

Construisez un projet Python avec Claude Code, uv, pyproject.toml, pytest, Ruff, FastAPI et une itération sûre.

Python avec Claude Code : guide uv, pytest, Ruff et FastAPI

Avec Claude Code, le vrai risque pour un débutant Python n’est pas l’absence de code. Le risque est d’obtenir un projet qui semble complet mais que personne ne sait installer, tester ou corriger. Un environnement virtuel différent, un import cassé, un pytest absent ou un formatage non configuré suffisent à bloquer l’apprentissage.

Ce guide propose une base courte et vérifiable. Nous allons créer l’environnement avec uv ou venv, centraliser la configuration dans pyproject.toml, ajouter une petite API FastAPI, proposer une CLI optionnelle, écrire des tests avec pytest et contrôler le style avec ruff. Claude Code devient utile quand chaque demande se termine par une preuve.

Gardez les références officielles ouvertes : Claude Code, le guide Python pour écrire pyproject.toml, l’installation de uv, pytest, Ruff et les premiers pas de FastAPI.

Commencer par une cible petite

Ne demandez pas dès le départ l’authentification, la base de données, Docker, CI et les tâches asynchrones. Pour apprendre, le premier jalon doit être facile à vérifier.

  • uv run pytest passe
  • uv run ruff check . et uv run ruff format . s’exécutent
  • FastAPI crée et liste une tâche
  • La CLI ajoute une tâche depuis le terminal
  • Claude Code indique les commandes exécutées
flowchart LR
  A["Brief de travail"] --> B["uv ou venv"]
  B --> C["pyproject.toml"]
  C --> D["Code dans src"]
  D --> E["pytest"]
  E --> F["ruff"]
  F --> G["Petite itération Claude Code"]

Le brief est le cadre de travail de l’agent. Il décrit l’objectif, les fichiers modifiables, la version de Python et les commandes de preuve. Pour rendre ces règles durables dans un dépôt, ajoutez aussi un CLAUDE.md bien structuré. Pour aller plus loin côté backend, lisez développer une API avec Claude Code et les stratégies de test.

Prompt initial pour Claude Code

Voici un prompt court mais exploitable.

Ajoute à ce dépôt une petite API de gestion de tâches pour Python 3.12.

Contraintes:
- Utilise uv pour les dépendances et centralise la configuration dans pyproject.toml.
- Place le code dans src/task_api/ et les tests dans tests/.
- Implémente POST /tasks et GET /tasks avec FastAPI.
- Ajoute des tests pytest pour le chemin nominal et un cas 404.
- ruff check et ruff format doivent passer.
- Avant modification, donne le plan. Après modification, liste les commandes exécutées.

Fichiers autorisés:
- pyproject.toml
- src/task_api/**
- tests/**

Cette demande évite le flou. Si Claude Code modifie un dossier sans rapport ou oublie les tests, le problème est visible immédiatement. Pour un débutant, c’est beaucoup plus utile qu’un grand bloc de code sans contexte.

Créer l’environnement avec uv ou venv

uv est pratique pour un nouveau projet car il est rapide et rend les commandes courtes. Si votre entreprise n’autorise pas son installation, utilisez venv. Le point essentiel est de choisir une méthode et de l’écrire dans le brief.

macOS ou Linux :

mkdir task-api
cd task-api
uv init --app --python 3.12
uv add "fastapi[standard]"
uv add --dev pytest ruff
mkdir -p src/task_api tests
touch src/task_api/__init__.py

Windows PowerShell :

mkdir task-api
cd task-api
uv init --app --python 3.12
uv add "fastapi[standard]"
uv add --dev pytest ruff
New-Item -ItemType Directory -Force src/task_api, tests
New-Item -ItemType File -Force src/task_api/__init__.py

Alternative venv :

python -m venv .venv
source .venv/bin/activate
python -m pip install --upgrade pip
python -m pip install "fastapi[standard]" pytest ruff
python -m venv .venv
.\.venv\Scripts\Activate.ps1
python -m pip install --upgrade pip
python -m pip install "fastapi[standard]" pytest ruff

Centraliser pyproject.toml

Pour une base pédagogique, évitez de disperser les règles entre plusieurs fichiers. Ce pyproject.toml suffit pour les dépendances, le script de console, pytest et Ruff.

[project]
name = "task-api"
version = "0.1.0"
description = "Small FastAPI and CLI sample for Claude Code practice"
requires-python = ">=3.11"
dependencies = [
  "fastapi[standard]>=0.115.0",
]

[project.scripts]
task-api = "task_api.cli:main"

[dependency-groups]
dev = [
  "pytest>=8.0.0",
  "ruff>=0.8.0",
]

[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

[tool.hatch.build.targets.wheel]
packages = ["src/task_api"]

[tool.pytest.ini_options]
testpaths = ["tests"]
pythonpath = ["src"]

[tool.ruff]
line-length = 100
target-version = "py311"

[tool.ruff.lint]
select = ["E", "F", "I", "B", "UP"]

Ajouter FastAPI et une CLI minimale

Placez ce code dans src/task_api/main.py. Il utilise la mémoire locale, donc ce n’est pas une base de production. C’est volontaire : avant la base de données, il faut comprendre les routes, les modèles et les erreurs.

from fastapi import FastAPI, HTTPException
from pydantic import BaseModel, Field

app = FastAPI(title="Task API")


class TaskCreate(BaseModel):
    title: str = Field(min_length=1, max_length=80)


class Task(BaseModel):
    id: int
    title: str
    done: bool = False


_tasks: dict[int, Task] = {}
_next_id = 1


@app.post("/tasks", response_model=Task, status_code=201)
def create_task(payload: TaskCreate) -> Task:
    global _next_id
    task = Task(id=_next_id, title=payload.title)
    _tasks[task.id] = task
    _next_id += 1
    return task


@app.get("/tasks", response_model=list[Task])
def list_tasks() -> list[Task]:
    return list(_tasks.values())


@app.patch("/tasks/{task_id}/done", response_model=Task)
def mark_done(task_id: int) -> Task:
    task = _tasks.get(task_id)
    if task is None:
        raise HTTPException(status_code=404, detail="Task not found")
    updated = task.model_copy(update={"done": True})
    _tasks[task_id] = updated
    return updated
uv run fastapi dev src/task_api/main.py

Pour une CLI, créez src/task_api/cli.py.

import argparse
import json
from pathlib import Path

DB_PATH = Path("tasks.json")


def load_tasks() -> list[dict[str, object]]:
    if not DB_PATH.exists():
        return []
    return json.loads(DB_PATH.read_text(encoding="utf-8"))


def save_tasks(tasks: list[dict[str, object]]) -> None:
    DB_PATH.write_text(json.dumps(tasks, ensure_ascii=False, indent=2), encoding="utf-8")


def add_task(title: str) -> dict[str, object]:
    tasks = load_tasks()
    task = {"id": len(tasks) + 1, "title": title, "done": False}
    tasks.append(task)
    save_tasks(tasks)
    return task


def main() -> None:
    parser = argparse.ArgumentParser(description="Task CLI")
    subparsers = parser.add_subparsers(dest="command", required=True)
    add_parser = subparsers.add_parser("add")
    add_parser.add_argument("title")
    args = parser.parse_args()
    if args.command == "add":
        task = add_task(args.title)
        print(f"Added #{task['id']}: {task['title']}")


if __name__ == "__main__":
    main()
uv run task-api add "write pytest"

Sécuriser avec pytest et Ruff

Ajoutez tests/test_main.py, puis gardez les mêmes commandes à chaque itération.

import pytest
from fastapi.testclient import TestClient

from task_api import main
from task_api.main import app


@pytest.fixture(autouse=True)
def clean_tasks() -> None:
    main._tasks.clear()
    main._next_id = 1


def test_create_and_list_tasks() -> None:
    client = TestClient(app)
    response = client.post("/tasks", json={"title": "Write pytest"})
    assert response.status_code == 201
    assert response.json()["title"] == "Write pytest"
    list_response = client.get("/tasks")
    assert list_response.status_code == 200
    assert len(list_response.json()) == 1


def test_mark_done_returns_404_for_missing_task() -> None:
    client = TestClient(app)
    response = client.patch("/tasks/999/done")
    assert response.status_code == 404
    assert response.json()["detail"] == "Task not found"
uv run pytest
uv run ruff check .
uv run ruff format .

Cas d’usage concrets

Premier cas : une API d’apprentissage. Elle montre les routes, Pydantic, OpenAPI, pytest et Ruff dans un périmètre court. Deuxième cas : une CLI d’automatisation pour nettoyer des CSV, renommer des fichiers ou préparer un rapport. Troisième cas : ajouter des tests à un script Python existant avant de le refactorer. Quatrième cas : construire un support de formation commun pour une équipe.

Ces usages créent aussi une transition naturelle vers les produits Claude Code ou la formation et consultation. Le lecteur reçoit d’abord du code utilisable, puis voit clairement quand un accompagnement devient pertinent.

Pièges fréquents

Ne laissez pas le gestionnaire de paquets implicite, sinon pip, poetry, uv et requirements.txt peuvent se mélanger. Ne démarrez pas par la base de données et JWT. Vérifiez les diffs Ruff avant de les accepter. Corrigez les imports avec pythonpath = ["src"] ou une installation correcte du paquet. Et ne collez jamais de secrets, données client ou URLs de production dans le prompt.

Résultat vérifié

Pour cette mise à jour, j’ai suivi l’ordre utilisé par Masa dans les supports débutants : environnement, pyproject.toml, petite API FastAPI, tests, puis Ruff. Le résultat pratique est que chaque erreur devient localisable : environnement, import, comportement testé ou formatage. C’est ce cadre qui rend Claude Code fiable pour apprendre, former une équipe et améliorer du code Python réel.

#Claude Code #Python #uv #pytest #FastAPI
Gratuit

PDF gratuit: cheatsheet Claude Code

Saisissez votre email et téléchargez une page avec commandes, habitudes de review et workflow sûr.

Nous protégeons vos données et n'envoyons pas de spam.

Masa

À propos de l'auteur

Masa

Ingénieur spécialisé dans les workflows pratiques avec Claude Code.