---
title: "Python-logging instellen met de juiste logniveaus en exceptions met traceback"
description: "Python logging drukt alleen WARNING en hoger af tot je het configureert. Hier is de configuratie van 3 regels, de 5 logniveaus en het loggen van een exception met traceback, uit runs op Python 3.13."
canonical: "https://logbrew.co/nl/guides/python-logging"
last_updated: "2026-11-10"
---

# Python-logging instellen met de juiste logniveaus en exceptions met traceback

Python `logging` drukt alleen WARNING en hoger af tot je het configureert. Hier is de configuratie van 3 regels, de 5 logniveaus en het loggen van een exception met traceback, uit runs op Python 3.13.

Getest op 10 november 2026 met Python 3.13.5 en logbrew-sdk 0.1.29

Door [Furkan Erday](https://github.com/furkanerday). Furkan Erday is de oprichter van LogBrew. Hij bouwt LogBrew elke dag met Claude Code en Codex.

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

## Wat elk Python-logniveau doet zonder configuratie, en in LogBrew

| Logaanroep | Afgedrukt zonder configuratie | Eigen niveau in LogBrew |
| --- | --- | --- |
| `log.debug()` | Weggelaten | Samengevoegd met `info` |
| `log.info()` | Weggelaten | `info` |
| `log.warning()` | `WARNING:root:` | `warning` |
| `log.error()` | `ERROR:root:` | `error` |
| `log.critical()` | `CRITICAL:root:` | `critical` |

5 aanroepen op de root logger zonder configuratie, daarna dezelfde 5 via de LogBrew-handler. Een volle mok betekent afgedrukt, of bewaard als eigen niveau.

## Logging instellen in 3 regels

### Roep basicConfig() 1 keer aan, vóór de eerste logaanroep

`basicConfig()` zet het niveau en het regelformaat van de root logger. Zonder configuratie drukt Python alleen WARNING en hoger af, als `WARNING:root:keg below 10%`, en laat het DEBUG en INFO weg.

```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")
```

Uitvoer

```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
```

### Geef elke module een eigen logger

`logging.getLogger(__name__)` geeft elke module een eigen logger, zodat elke regel de module noemt waar hij vandaan komt. Gebruik de root logger alleen voor `basicConfig()`.

### Lees het niveau uit de omgeving

`basicConfig()` accepteert een niveaunaam als tekst. Draai dit met `LOG_LEVEL=DEBUG` en de debug-regel verschijnt, zonder codewijziging.

```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")
```

Uitvoer

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

### Geef force=True mee om opnieuw te configureren

Python negeert een 2e `basicConfig()`-aanroep als de root logger al een handler heeft. Geef `force=True` mee om de handlers te vervangen, bijvoorbeeld in 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")
```

Uitvoer

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

## Log elke exception met traceback

### Roep log.exception() aan binnen except

`log.exception()` logt op ERROR en voegt de traceback toe. Geef `exc_info=True` mee aan een aanroep op elk ander niveau om daar hetzelfde te doen.

```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")
```

Uitvoer

```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'
```

### Stuur elke regel naar LogBrew met de logging-handler

Voeg `LogBrewLoggingHandler` toe aan je logger. Elk record wordt een LogBrew-log met zijn niveau, loggernaam, bestand en regel. De naam en het bericht van de exception gaan mee, net als de waarden in `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")
```

Uitvoer

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

### Lees de log terug met de exception-velden

`logbrew read logs --severity error --json` geeft de regel terug met `exceptionName`, `exceptionMessage`, het bestand, de functie, het regelnummer en je `order_id`.

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

Uitvoer

```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"
  }
}
```

### Vang de crash die het proces beëindigt

`install_process_error_capture()` haakt in op `sys.excepthook`. Een exception die niemand afvangt wordt een issue op niveau `critical` met `handled: false`, vastgelegd voordat het proces stopt met 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
```

Uitvoer

```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}}
```

## Wat we zagen in onze test

Zonder configuratie drukten 5 aanroepen op de root logger 3 regels af naar stderr en lieten ze de DEBUG- en INFO-aanroepen weg. De standaardregel is het niveau, de loggernaam en het bericht, als `WARNING:root:keg below 10%`.

Een 2e `basicConfig()`-aanroep veranderde niets tot we `force=True` meegaven. Via de LogBrew-handler kwamen DEBUG- en INFO-records aan als `info`, WARNING als `warning`, ERROR als `error` en CRITICAL als `critical`.

`log.exception()` voegde `exceptionName` en `exceptionMessage` toe aan de LogBrew-log. Met `include_exception_text=True` op de handler kwam de volledige traceback aan als `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")
```

Uitvoer

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

## De 5 logniveaus en wanneer je ze gebruikt

DEBUG is voor de waarden die je nodig hebt terwijl je een bug oplost, zoals de kegdruk, de SQL-tekst of het aantal pogingen. Zet het uit in productie.

INFO legt vast wat het programma deed, zoals een tap die openging of een order die betaald is. WARNING legt vast wat misging maar afgehandeld werd, zoals een keg onder 10%. ERROR legt een request of job vast die mislukte, zoals een lege keg. CRITICAL legt vast wat het programma stopt, zoals een koeling die offline is.

Log elke exception 1 keer, waar je hem afhandelt. Een regel op elk niveau van de call stack stuurt 3 meldingen voor 1 fout.

```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))
```

Uitvoer

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

## Wat LogBrew vastlegt

Elk record wordt 1 log met zijn niveau, loggernaam, bestandsnaam, functie, regelnummer en module. Primitieve waarden uit `extra={}` worden velden waarop je kunt filteren, en `metadata={}` op de handler voegt aan elke regel een veld toe, zoals `service` hierboven.

Bij een exception krijgt de log `exceptionName` en `exceptionMessage`. Geef `include_exception_text=True` mee aan de handler om ook de tracebacktekst op te slaan.

`install_process_error_capture()` maakt van een niet-afgevangen exception een issue op niveau `critical`, met het exceptiontype, de stackframes en het mechanisme `python.excepthook`.

## Veelgestelde vragen

### Wat is het standaard logniveau in Python?

WARNING. Zonder `basicConfig()`-aanroep drukt de root logger WARNING, ERROR en CRITICAL af naar stderr als `WARNING:root:message`, en laat hij DEBUG en INFO weg.

### Waarom doet logging.basicConfig niets?

De root logger heeft al een handler, van een eerdere `basicConfig()`-aanroep of van een library, dus Python negeert de aanroep. Geef `force=True` mee om de handlers te vervangen.

### Wat is het verschil tussen logging.error en logging.exception?

`log.exception()` is `log.error()` met `exc_info=True`. Het logt op ERROR en voegt de traceback toe. Roep het alleen aan binnen een `except`-blok.

### Wat zijn de logniveaus van Python op volgorde?

DEBUG 10, INFO 20, WARNING 30, ERROR 40, CRITICAL 50. Een logger laat een record door als zijn nummer gelijk is aan of hoger dan het niveau dat je instelt.

### Moet ik print() of logging gebruiken in Python?

Gebruik `logging`. `print()` heeft geen niveau, geen tijdstempel, geen loggernaam en geen handler. Met `logging` zet je regels per module aan en stuur je ze naar een bestand of naar LogBrew.

## Zie elke Python-exception met traceback

De LogBrew Python-SDK stuurt elke logregel met niveau, logger, bestand en regel, en maakt van een niet-afgevangen exception een issue met stacktrace. Begin met het ruime gratis abonnement, zonder creditcard.

[Gratis beginnen](https://logbrew.co/nl)

## Bronnen

- [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)

## Meer handleidingen voor agents en Python

- [Een MCP-server toevoegen aan Claude Code en Codex](https://logbrew.co/nl/guides/mcp-server-claude-code-codex)
- [AGENTS.md gebruiken in Claude Code en Codex](https://logbrew.co/nl/guides/agents-md)
- [Claude overloaded error 529 en rate limit error 429 oplossen](https://logbrew.co/nl/guides/claude-overloaded-rate-limit-error)
- [Structured logging met een logformaat en logniveaus die je per veld doorzoekt](https://logbrew.co/nl/guides/structured-logging)
- [Fouten oplossen in Claude Code, Codex, JavaScript en Python](https://logbrew.co/nl/guides)
