---
title: "Configurer le logging Python avec les bons niveaux de log et la capture des exceptions"
description: "Sans configuration, Python logging n’affiche que WARNING et au-dessus. Voici la configuration en 3 lignes, les 5 niveaux de log et le log d’une exception avec son traceback, sur Python 3.13."
canonical: "https://logbrew.co/fr/guides/python-logging"
last_updated: "2026-11-10"
---

# Configurer le logging Python avec les bons niveaux de log et la capture des exceptions

Sans configuration, Python `logging` n’affiche que WARNING et au-dessus. Voici la configuration en 3 lignes, les 5 niveaux de log et le log d’une exception avec son traceback, sur Python 3.13.

Testé le 10 novembre 2026 avec Python 3.13.5 et logbrew-sdk 0.1.29

Par [Furkan Erday](https://github.com/furkanerday). Furkan Erday est le fondateur de LogBrew. Il développe LogBrew avec Claude Code et Codex tous les jours.

Canonical: https://logbrew.co/fr/guides/python-logging

## Ce que fait chaque niveau de log Python sans configuration, et dans LogBrew

| Appel de logging | Affiché sans configuration | Niveau à part dans LogBrew |
| --- | --- | --- |
| `log.debug()` | Ignoré | Fusionné dans `info` |
| `log.info()` | Ignoré | `info` |
| `log.warning()` | `WARNING:root:` | `warning` |
| `log.error()` | `ERROR:root:` | `error` |
| `log.critical()` | `CRITICAL:root:` | `critical` |

5 appels sur le logger racine sans configuration, puis les mêmes 5 via le handler LogBrew. Une chope pleine signifie affiché, ou conservé comme niveau à part.

## Configurer le logging en 3 lignes

### Appeler basicConfig() une fois, avant le premier appel de log

`basicConfig()` fixe le niveau et le format de ligne du logger racine. Sans configuration, Python n’affiche que WARNING et au-dessus, sous la forme `WARNING:root:keg below 10%`, et ignore DEBUG et INFO.

```bash
import logging

logging.basicConfig(
    level=logging.INFO,
    format="%(asctime)s %(levelname)s %(name)s %(message)s",
)
log = logging.getLogger("taproom")

log.debug("keg pressure read")
log.info("tap opened")
log.warning("keg below 10%")
log.error("keg empty")
log.critical("cooler offline")
```

Sortie

```text
2026-11-10 08:34:04,828 INFO taproom tap opened
2026-11-10 08:34:04,828 WARNING taproom keg below 10%
2026-11-10 08:34:04,828 ERROR taproom keg empty
2026-11-10 08:34:04,828 CRITICAL taproom cooler offline
```

### Nommer un logger par module

`logging.getLogger(__name__)` donne à chaque module son propre logger, et chaque ligne nomme ainsi le module d’où elle vient. Gardez le logger racine pour `basicConfig()` seulement.

### Lire le niveau depuis l’environnement

`basicConfig()` accepte un nom de niveau en texte. Lancez ceci avec `LOG_LEVEL=DEBUG` et la ligne de debug apparaît, sans changer le code.

```bash
import logging
import os

logging.basicConfig(level=os.environ.get("LOG_LEVEL", "INFO"))
log = logging.getLogger("taproom")
log.debug("keg pressure read")
log.info("tap opened")
```

Sortie

```text
DEBUG:taproom:keg pressure read
INFO:taproom:tap opened
```

### Passer force=True pour reconfigurer

Python ignore un second appel à `basicConfig()` quand le logger racine a déjà un handler. Passez `force=True` pour remplacer les handlers, par exemple dans les tests.

```bash
import logging

logging.basicConfig(level=logging.WARNING)
logging.basicConfig(level=logging.DEBUG)
logging.debug("second basicConfig: not printed")
logging.basicConfig(level=logging.DEBUG, force=True)
logging.debug("basicConfig with force=True: printed")
```

Sortie

```text
DEBUG:root:basicConfig with force=True: printed
```

## Logger chaque exception avec son traceback

### Appeler log.exception() dans le bloc except

`log.exception()` logge au niveau ERROR et ajoute le traceback. Passez `exc_info=True` à un appel de n’importe quel autre niveau pour faire pareil à ce niveau.

```bash
import logging

logging.basicConfig(level=logging.INFO, format="%(levelname)s %(name)s %(message)s")
log = logging.getLogger("taproom")
taps = {"ipa": 12}

def pour(beer):
    return taps[beer]

try:
    pour("stout")
except KeyError:
    log.exception("pour failed")
```

Sortie

```text
ERROR taproom pour failed
Traceback (most recent call last):
  File "app.py", line 11, in <module>
    pour("stout")
    ~~~~^^^^^^^^^
  File "app.py", line 8, in pour
    return taps[beer]
           ~~~~^^^^^^
KeyError: 'stout'
```

### Envoyer chaque ligne à LogBrew avec le handler de logging

Ajoutez `LogBrewLoggingHandler` à votre logger. Chaque record devient un log LogBrew avec son niveau, le nom du logger, le fichier et la ligne. Le nom et le message de l’exception suivent, tout comme les valeurs de `extra={}`.

```bash
import logging
import os

from logbrew_sdk import HttpTransport, LogBrewClient, LogBrewLoggingHandler

client = LogBrewClient.create(api_key=os.environ["LOGBREW_SERVER_API_KEY"])
transport = HttpTransport()
log = logging.getLogger("taproom")
log.addHandler(LogBrewLoggingHandler(client, transport, metadata={"service": "taproom"}))
log.setLevel(logging.INFO)

taps = {"ipa": 12}

def pour(beer):
    return taps[beer]

try:
    pour("stout")
except KeyError:
    log.exception("pour failed", extra={"order_id": "ord_42"})

response = client.flush(transport)
print("HTTP", response.status_code, "accepted", response.accepted_events, "logs")
```

Sortie

```text
HTTP 200 accepted 1 logs
```

### Relire le log avec ses champs d’exception

`logbrew read logs --severity error --json` renvoie la ligne avec `exceptionName`, `exceptionMessage`, le fichier, la fonction, le numéro de ligne et votre `order_id`.

```bash
logbrew read logs --project <project_id> --severity error --since 1h --json | jq '.[0] | {level, message, logger: .attributes.logger, metadata: .attributes.metadata}'
```

Sortie

```text
{
  "level": "error",
  "message": "pour failed",
  "logger": "taproom",
  "metadata": {
    "exceptionMessage": "'stout'",
    "exceptionName": "KeyError",
    "fileName": "send.py",
    "functionName": "<module>",
    "levelName": "ERROR",
    "levelNumber": 40,
    "lineNumber": 20,
    "module": "send",
    "order_id": "ord_42",
    "processName": "MainProcess",
    "service": "taproom",
    "threadName": "MainThread"
  }
}
```

### Attraper le plantage qui termine le processus

`install_process_error_capture()` se branche sur `sys.excepthook`. Une exception que personne n’attrape devient un problème de niveau `critical` avec `handled: false`, capturé avant que le processus se termine avec le code 1.

```bash
import atexit
import json
import os

from logbrew_sdk import LogBrewClient, RecordingTransport, install_process_error_capture

transport = RecordingTransport.always_accept()
client = LogBrewClient.create(api_key=os.environ["LOGBREW_SERVER_API_KEY"], transport=transport)
install_process_error_capture(client, on_capture_error=print)


@atexit.register
def show_captured_issue() -> None:
    issue = json.loads(transport.last_body())["events"][0]["attributes"]
    print(json.dumps({k: issue[k] for k in ("title", "level")}), json.dumps(issue["exception"]))


kegs = {"ipa": 3}
kegs["stout"] -= 1
```

Sortie

```text
Traceback (most recent call last):
  File "<stdin>", line 19, in <module>
KeyError: 'stout'
{"title": "KeyError", "level": "critical"} {"type": "KeyError", "mechanism": {"type": "python.excepthook", "handled": false}}
```

## Ce que nous avons constaté en testant

Sans configuration, 5 appels sur le logger racine ont affiché 3 lignes sur stderr et ignoré les appels DEBUG et INFO. La ligne par défaut est le niveau, le nom du logger et le message, sous la forme `WARNING:root:keg below 10%`.

Un second appel à `basicConfig()` n’a rien changé tant que nous n’avons pas passé `force=True`. Via le handler LogBrew, les records DEBUG et INFO sont arrivés en `info`, WARNING en `warning`, ERROR en `error` et CRITICAL en `critical`.

`log.exception()` a ajouté `exceptionName` et `exceptionMessage` au log LogBrew. Avec `include_exception_text=True` sur le handler, le traceback complet est arrivé en `exceptionText`.

```bash
import logging

logging.debug("keg pressure read")
logging.info("tap opened")
logging.warning("keg below 10%")
logging.error("keg empty")
logging.critical("cooler offline")
```

Sortie

```text
WARNING:root:keg below 10%
ERROR:root:keg empty
CRITICAL:root:cooler offline
```

## Les 5 niveaux de log et quand utiliser chacun

DEBUG sert aux valeurs dont vous avez besoin pendant que vous corrigez un bug, comme la pression du fût, le texte SQL ou le nombre de tentatives. Laissez-le éteint en production.

INFO enregistre ce que le programme a fait, comme une tireuse ouverte ou une commande payée. WARNING enregistre ce qui a mal tourné mais a été géré, comme un fût sous les 10 %. ERROR enregistre une requête ou un job qui a échoué, comme un fût vide. CRITICAL enregistre ce qui arrête le programme, comme une chambre froide hors service.

Loggez chaque exception une fois, là où vous la gérez. Une ligne à chaque étage de la stack envoie 3 alertes pour 1 échec.

```bash
import logging

for name in ("DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"):
    print(name, logging.getLevelName(name))
print("root logger level:", logging.getLevelName(logging.getLogger().level))
```

Sortie

```text
DEBUG 10
INFO 20
WARNING 30
ERROR 40
CRITICAL 50
root logger level: WARNING
```

## Ce que LogBrew enregistre

Chaque record devient 1 log avec son niveau, le nom du logger, le nom du fichier, la fonction, le numéro de ligne et le module. Les valeurs primitives de `extra={}` deviennent des champs sur lesquels vous pouvez filtrer, et `metadata={}` sur le handler ajoute un champ à chaque ligne, comme `service` ci-dessus.

Sur une exception, le log reçoit `exceptionName` et `exceptionMessage`. Passez `include_exception_text=True` au handler pour stocker aussi le texte du traceback.

`install_process_error_capture()` transforme une exception non attrapée en problème de niveau `critical`, avec le type de l’exception, les frames de la stack et le mécanisme `python.excepthook`.

## Questions fréquentes

### Quel est le niveau de logging par défaut en Python ?

WARNING. Sans appel à `basicConfig()`, le logger racine affiche WARNING, ERROR et CRITICAL sur stderr sous la forme `WARNING:root:message`, et ignore DEBUG et INFO.

### Pourquoi logging.basicConfig ne fait rien ?

Le logger racine a déjà un handler, venu d’un appel antérieur à `basicConfig()` ou d’une bibliothèque, donc Python ignore l’appel. Passez `force=True` pour remplacer les handlers.

### Quelle différence entre logging.error et logging.exception ?

`log.exception()` est `log.error()` avec `exc_info=True`. Il logge au niveau ERROR et ajoute le traceback. Appelez-le seulement dans un bloc `except`.

### Quels sont les niveaux de logging Python, dans l’ordre ?

DEBUG 10, INFO 20, WARNING 30, ERROR 40, CRITICAL 50. Un logger laisse passer un record quand son nombre est égal ou supérieur au niveau que vous avez fixé.

### Faut-il utiliser print() ou logging en Python ?

Utilisez `logging`. `print()` n’a ni niveau, ni horodatage, ni nom de logger, ni handler. Avec `logging`, vous activez les lignes par module et les envoyez vers un fichier ou vers LogBrew.

## Voyez chaque exception Python avec son traceback

Le SDK Python de LogBrew envoie chaque ligne de log avec son niveau, son logger, son fichier et sa ligne, et transforme une exception non attrapée en problème avec sa stack trace. Commencez avec le forfait Free généreux, sans carte bancaire.

[Commencer gratuitement](https://logbrew.co/fr)

## Sources

- [Python docs, Logging HOWTO](https://docs.python.org/3/howto/logging.html)
- [Python docs, logging module](https://docs.python.org/3/library/logging.html)
- [python/cpython#78078](https://github.com/python/cpython/issues/78078)

## Autres guides pour les agents et Python

- [Ajouter un serveur MCP à Claude Code et Codex](https://logbrew.co/fr/guides/mcp-server-claude-code-codex)
- [Utiliser AGENTS.md dans Claude Code et Codex](https://logbrew.co/fr/guides/agents-md)
- [Corriger l’erreur Claude overloaded 529 et l’erreur rate limit 429](https://logbrew.co/fr/guides/claude-overloaded-rate-limit-error)
- [Logging structuré avec un format de log et des niveaux que vous cherchez par champ](https://logbrew.co/fr/guides/structured-logging)
- [Corriger les erreurs dans Claude Code, Codex, JavaScript et Python](https://logbrew.co/fr/guides)
