<!--
  canonical-url: https://www.avonture.be/fr/blog/python-fastapi
  published:     2025-02-09
  This is a static plain-Markdown mirror generated at build time.
  Visit the canonical URL above for the fully rendered page, with images and interactive components.
-->

# Python - Fast API - Créez votre API JSON en Python en une minute

> Construisez votre première API JSON Python avec FastAPI en moins d'une minute ! Ce tutoriel couvre la configuration Docker, la documentation d'API automatisée (Swagger/ReDoc) et le hot-reload pour développer rapidement.

---
![Python - Fast API - Créez votre API JSON en Python en une minute](/img/v2/api.webp)

**TL;DR**

Créez votre première API JSON Python avec FastAPI en une minute seulement. Ce tutoriel vous guide dans la mise en place d'une API basique avec Docker, depuis un simple « Hello World » jusqu'à un générateur de blagues interactif. Vous découvrirez les fonctionnalités puissantes de FastAPI comme la documentation d'API interactive générée automatiquement (Swagger et ReDoc) et comment configurer un environnement de développement avec hot-reload pour des cycles de développement rapides.

> TLDR : une minute, c'est le temps qu'il vous faudra pour copier/coller le contenu de deux fichiers et lancer une commande Docker.

Ça paraît dingue, mais c'est VRAI. Il vous faudra juste une minute pour créer l'exemple ci-dessous : créer le répertoire de votre projet, créer deux fichiers et lancer deux commandes Docker et ... c'est fini.

En tant que programmeur PHP, quand j'ai pris le temps de lire un article de blog sur FastAPI, j'ai pensé **Nodidju ! Ç' n'est nén pussibe** (*Bon sang ! Ce n'est pas possible*).

Avec seulement deux fichiers, nous allons construire notre propre image Docker avec Python et FastAPI installés et coder notre application REST API. Pas plus de deux !

Impossible de ne pas essayer tout de suite et ... wow ... c'est VRAI !

Voici le résultat : rendez-vous sur `http://127.0.0.1:`82 et obtenez votre première réponse JSON.

> Screenshot — http\://127.0.0.1:82
>
> Hello World

## Pourquoi ça fonctionne {#why-it-works}

* `main.py` définit une route (`/`) avec deux lignes de Python — FastAPI transforme cette fonction en endpoint HTTP fonctionnel, sans aucune configuration de serveur à écrire.
* Le `Dockerfile` regroupe Python, FastAPI et votre code dans une seule image d'environ 184 Mo, donc il n'y a rien à installer sur votre host à part Docker lui-même.

## Créer notre première API {#creating-our-first-api}

Comme toujours, nous allons construire un exemple complètement fonctionnel. Ça ne pourrait pas être plus simple ; vous allez voir.

Créez un dossier bidon et placez-vous dedans :

```bash
$ mkdir /tmp/fastapi && cd $_
```

Dans ce dossier, créez un nouveau fichier appelé `Dockerfile` avec le contenu suivant :

**Dockerfile**

```docker
# We'll use the latest version of Python and the smaller image in size (i.e. `slim`)
FROM python:slim

# We'll define the default folder in the image to /app
WORKDIR /app

# The only dependency we need is fastapi
RUN pip install --no-cache-dir 'fastapi[standard]'

# We need to copy our Python script in the image
COPY main.py main.py

# And we'll run FastAPI and call our script. We'll expose the script on port 82
CMD ["fastapi", "run", "main.py", "--port", "82"]
```

La taille finale de l'image sera d'environ 184 Mo, c'est-à-dire presque rien.

Comme vous l'avez vu, il nous faut un fichier appelé `main.py` ; créons-le :

**main.py**

```python
from fastapi import FastAPI

app = FastAPI()

@app.get("/")
def read_root():
    return {"Hello": "World"}
```

Ce code très simple définit une route appelée `/`. C'est une méthode `GET` et nous allons retourner un objet JSON :

```json
{
  "Hello": "World"
}
```

Vous savez quoi ? C'est déjà terminé.

## Lancer notre API {#running-our-api}

Il nous faut construire notre image Docker et la lancer :

```bash
$ docker build -t python-fastapi . && docker run -p 82:82 python-fastapi
```

Une fois fait, rendez-vous sur `http://127.0.0.1
:
82` et vous obtiendrez la même réponse JSON que celle montrée en haut de cet article ; dingue non ?

## Documentation automatisée de votre API {#automated-documentation-of-your-api}

Et ce n'est que le début : FastAPI fournit une API auto-documentée basée sur le schéma OpenAPI. *Ce schéma n'est pas seulement de la documentation : il peut aussi être linté, voir [Validate your OpenAPI schema against the Belgif REST standards](/blog/belgif-api-linter).*

Rendez-vous sur `http://127.0.0.1
:
82
/docs` et vous le verrez en action :

> Screenshot — http\://127.0.0.1:82/docs
>
> Documentation automatisée - Swagger UI

Il existe un second template, alternatif, appelé ReDoc. Vous pouvez y accéder via l'endpoint `redoc`, c'est-à-dire `http://127.0.0.1
:
82
/redoc` :

> Screenshot — http\://127.0.0.1:82/redoc
>
> Documentation automatisée - Redoc

## Amusons-nous - Créer un générateur de blagues {#lets-play---creating-a-joke-generator}

Nous allons construire un script générateur de blagues. Notre objectif : obtenir une blague au hasard ou une blague précise (du genre *Donne-moi la troisième blague que tu connais*).

Pour cela, nous allons mettre à jour notre script `main.py` et, comme nous ferons probablement plus d'une modification, nous allons monter notre dossier de l'host dans le container.

Pourquoi ? [Monter notre dossier](/blog/docker-volume) dans le container nous permettra de modifier le script et de simplement rafraîchir la page web pour voir le changement.

La seule chose à faire est de lancer notre container comme ceci : `docker run -v .:/app -p 
82
:82 python-fastapi` ... mais ça n'a pas fonctionné comme prévu.

> **FastAPI utilise Uvicorn sous le capot:**
>
> Uvicorn est une implémentation de serveur web pour Python. Uvicorn possède un mécanisme de cache intégré donc, même si nous avons mis à jour la source de notre script `main.py`, nous obtiendrons encore l'ancienne version.
>
> Nous devons démarrer Uvicorn avec un mécanisme de « hot reload ».

### Recréer l'image Docker pour le hot reload (passez cette étape si `docker run -v .:/app` rafraîchissait déjà chez vous) {#recreating-the-docker-image-for-hot-reload-skip-this-if-docker-run--v-app-already-refreshed-for-you}

Arrêtez d'abord le container en cours d'exécution : retournez dans votre console et appuyez sur `CTRL`+`C` pour arrêter le container. Nous allons aussi supprimer le container. Vous pouvez le faire depuis `Docker Desktop` : cliquez sur le menu `Containers` et tuez votre container *Python - Fastapi*. Supprimez aussi l'image appelée `python-fastapi`.

> **Note:**
>
> `python-fastapi` est le nom de l'image Docker que nous avons construite plus tôt.

Si vous préférez la ligne de commande, vous pouvez obtenir le même résultat en lançant ces deux commandes :

```bash
$ docker rm $(docker ps -aq --filter "ancestor=python-fastapi")
$ docker rmi python-fastapi --force
```

Maintenant, copiez/collez le contenu suivant dans votre `Dockerfile` existant :

**Dockerfile**

```docker
# We'll use the latest version of Python and the smaller image in size (i.e. `slim`)
FROM python:slim

# We'll define the default folder in the image to /app
WORKDIR /app

# The only dependency we need is fastapi
RUN pip install --no-cache-dir 'fastapi[standard]'

# We need to copy our Python script in the image
COPY main.py main.py

// highlight-start
# Run Uvicorn with hot reload so any changes to our main.py script will force
# the server to invalidate the cache and refresh the page.
CMD ["uvicorn", "main:app", "--reload", "--host", "0.0.0.0", "--port", "82"]
// highlight-end
```

Reconstruisez l'image et lancez un nouveau container, cette fois avec un volume, en exécutant ces commandes :

```bash
$ docker build -t python-fastapi . && docker run -v .:/app -p 82:82 python-fastapi
```

Nous avons maintenant une image Docker avec hot reload et nous avons monté notre dossier dans le container.

Modifiez votre script `main.py` comme ceci :

**main.py**

```python
from fastapi import FastAPI

app = FastAPI()

@app.get("/")
def read_root():
    # highlight-next-line
    return {"Hello": "Belgium!"}
```

Rafraîchissez votre page web, vous verrez Hello Belgium!. Modifiez votre `main.py` et remplacez `Belgium!` par `France`. Rechargez votre page web ; vous verrez Hello France. Super, nous avons un hot reload et nous pouvons vraiment commencer à jouer.

### Notre générateur de blagues {#our-joke-generator}

Nous allons mettre à jour notre script `main.py` comme ceci :

**main.py**

```python
// highlight-next-line
from random import choice
from fastapi import FastAPI

app = FastAPI()

// highlight-start
jokes = [
    "Why do programmers always mix up Halloween and Christmas? Because Oct 31 == Dec 25",
    "Why don't programmers like nature? Because it's full of bugs!",
    "How many programmers does it take to change a light bulb? None. That's a hardware problem.",
    "What do you call 8 hobbits? A hobbyte",
    "What is this [“hip”, ”hip”]? hip hip array!"
]

@app.get("/jokes")
async def get_jokes():
    """
    Returns a random joke from the list.
    """
    return {"joke": choice(jokes)}

@app.get("/jokes/{joke_id}")
def read_item(joke_id: int):
    """
    Returns a specific joke (between 0 and 4).
    """
    try:
        return {"joke": jokes[joke_id]}
    except IndexError:
        return {"error": f"Joke with ID {joke_id} not found."}, 404
// highlight-end
```

Vous le voyez immédiatement, je pense :

* j'ai défini un tableau avec cinq blagues, codées en dur ;
* j'ai défini une nouvelle route appelée `/jokes` qui affichera une blague au hasard ;
* et enfin j'ai défini une route `jokes/{joke_id}` pour pouvoir viser une blague précise (comme « Donne-moi la deuxième blague que tu connais »).

> **Utilisez un fichier externe plutôt que des blagues codées en dur:**
>
> En guise d'exercice, supprimez simplement la partie initialisation du tableau `jokes` et lisez plutôt les blagues depuis un fichier texte. Ce serait vraiment facile à faire.

Retournez dans votre navigateur et rendez-vous sur l'endpoint `jokes` (`http://127.0.0.1
:
82
/jokes`) et, hop, vous avez une blague au hasard.

> Screenshot — http\://127.0.0.1:82/jokes
>
> Obtenir une blague au hasard

Rafraîchissez la page ; encore et encore. Chaque fois vous obtiendrez une blague au hasard (parmi une liste de 5).

Si vous en voulez une précise, ajoutez simplement un ID après, comme `http://127.0.0.1
:
82
/jokes/1`

> Screenshot — http\://127.0.0.1:82/jokes/1
>
> Une blague précise

> **Note:**
>
> Notez que le tableau commence à la position 0 donc la première blague est celle-ci : `http://127.0.0.1
> :
> 82
> /jokes/0`.

#### Nos endpoints jokes sont documentés automatiquement {#our-jokes-endpoints-are-documented-automatically}

Et en revenant à la documentation (`http://127.0.0.1
:
82
/docs`), nous avons maintenant trois routes et, regardez, la docstring Python est utilisée pour décrire la route.

> Screenshot — http\://127.0.0.1:82/docs
>
> Swagger UI - Avec les nouvelles routes

Vraiment, vraiment impressionnant !

> **La documentation est interactive:**
>
> Et, encore plus impressionnant, vous pouvez jouer directement depuis la documentation, c'est-à-dire exécuter l'endpoint `jokes`. Il y a un bouton *Try it out* puis *Execute* pour voir l'endpoint en action.
>
> Plus d'infos <https://fastapi.tiangolo.com/tutorial/first-steps/#interactive-api-docs>

## Découvrir FastAPI {#discover-fastapi}

N'attendez plus, allez sur <https://fastapi.tiangolo.com/> pour voir plus d'exemples.

Et avant de publier votre API au monde entier, prenez cinq minutes pour lire [API REST - How to write good APIs](/blog/php-api-tips) : nommer correctement vos endpoints et choisir correctement vos codes de statut HTTP ne coûte rien le premier jour et coûte très cher le centième.

Lisez aussi le long tutoriel sur [Real Python - Using FastAPI to Build Python Web APIs](https://realpython.com/fastapi-python-web-apis/).
