---
title: "Skonfiguruj logowanie w Pythonie z właściwymi poziomami i przechwytywaniem wyjątków"
description: "Python logging wypisuje tylko WARNING i wyżej, dopóki go nie skonfigurujesz. Oto konfiguracja w 3 liniach, 5 poziomów logowania i logowanie wyjątku z tracebackiem, z testów na Pythonie 3.13."
canonical: "https://logbrew.co/pl/guides/python-logging"
last_updated: "2026-11-10"
---

# Skonfiguruj logowanie w Pythonie z właściwymi poziomami i przechwytywaniem wyjątków

Python `logging` wypisuje tylko WARNING i wyżej, dopóki go nie skonfigurujesz. Oto konfiguracja w 3 liniach, 5 poziomów logowania i logowanie wyjątku z tracebackiem, z testów na Pythonie 3.13.

Przetestowane 10 listopada 2026 z użyciem Python 3.13.5 i logbrew-sdk 0.1.29

Autor [Furkan Erday](https://github.com/furkanerday). Furkan Erday jest założycielem LogBrew. Codziennie rozwija LogBrew z pomocą Claude Code i Codex.

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

## Co robi każdy poziom logowania w Pythonie bez konfiguracji i w LogBrew

| Wywołanie logowania | Wypisane bez konfiguracji | Własny poziom w LogBrew |
| --- | --- | --- |
| `log.debug()` | Odrzucone | Scalone z `info` |
| `log.info()` | Odrzucone | `info` |
| `log.warning()` | `WARNING:root:` | `warning` |
| `log.error()` | `ERROR:root:` | `error` |
| `log.critical()` | `CRITICAL:root:` | `critical` |

5 wywołań na loggerze głównym bez konfiguracji, potem te same 5 przez handler LogBrew. Pełny kubek oznacza, że linia została wypisana albo zachowała własny poziom.

## Skonfiguruj logowanie w 3 liniach

### Wywołaj basicConfig() 1 raz, przed pierwszym logiem

`basicConfig()` ustawia poziom i format linii loggera głównego. Bez konfiguracji Python wypisuje tylko WARNING i wyżej, jako `WARNING:root:keg below 10%`, a DEBUG i INFO odrzuca.

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

Wynik

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

### Nazwij logger po każdym module

`logging.getLogger(__name__)` daje każdemu modułowi własny logger, więc każda linia mówi, z którego modułu pochodzi. Logger główny zostaw tylko dla `basicConfig()`.

### Czytaj poziom ze środowiska

`basicConfig()` przyjmuje nazwę poziomu jako tekst. Uruchom ten kod z `LOG_LEVEL=DEBUG`, a linia debug pojawi się bez zmiany w kodzie.

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

Wynik

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

### Przekaż force=True, aby skonfigurować ponownie

Python ignoruje 2. wywołanie `basicConfig()`, gdy logger główny ma już handler. Przekaż `force=True`, aby zastąpić handlery, na przykład w testach.

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

Wynik

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

## Loguj każdy wyjątek z tracebackiem

### Wywołaj log.exception() wewnątrz except

`log.exception()` loguje na poziomie ERROR i dołącza traceback. Przekaż `exc_info=True` do wywołania na dowolnym innym poziomie, aby zrobić to samo tam.

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

Wynik

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

### Wysyłaj każdą linię do LogBrew przez handler logowania

Dodaj `LogBrewLoggingHandler` do swojego loggera. Każdy rekord staje się logiem LogBrew z poziomem, nazwą loggera, plikiem i linią. Nazwa i komunikat wyjątku idą razem z nim, tak samo jak wartości z `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")
```

Wynik

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

### Odczytaj log z powrotem z polami wyjątku

`logbrew read logs --severity error --json` zwraca linię z `exceptionName`, `exceptionMessage`, plikiem, funkcją, numerem linii i Twoim `order_id`.

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

Wynik

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

### Złap awarię, która kończy proces

`install_process_error_capture()` podpina się pod `sys.excepthook`. Wyjątek, którego nikt nie złapie, staje się problemem na poziomie `critical` z `handled: false`, przechwyconym, zanim proces zakończy się kodem 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
```

Wynik

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

## Co zobaczyliśmy podczas testu

Bez konfiguracji 5 wywołań na loggerze głównym wypisało 3 linie na stderr i odrzuciło wywołania DEBUG i INFO. Domyślna linia to poziom, nazwa loggera i komunikat, jak `WARNING:root:keg below 10%`.

2. wywołanie `basicConfig()` nic nie zmieniło, dopóki nie przekazaliśmy `force=True`. Przez handler LogBrew rekordy DEBUG i INFO dotarły jako `info`, WARNING jako `warning`, ERROR jako `error`, a CRITICAL jako `critical`.

`log.exception()` dodał do logu LogBrew `exceptionName` i `exceptionMessage`. Z `include_exception_text=True` na handlerze pełny traceback dotarł jako `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")
```

Wynik

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

## 5 poziomów logowania i kiedy używać każdego

DEBUG jest dla wartości potrzebnych, gdy naprawiasz błąd, jak ciśnienie w kegu, tekst SQL albo liczba ponownych prób. Na produkcji trzymaj go wyłączonego.

INFO zapisuje, co program zrobił, jak otwarty kran albo opłacone zamówienie. WARNING zapisuje, co poszło źle, ale zostało obsłużone, jak keg poniżej 10%. ERROR zapisuje żądanie albo zadanie, które się nie udało, jak pusty keg. CRITICAL zapisuje to, co zatrzymuje program, jak chłodnia offline.

Loguj każdy wyjątek 1 raz, tam gdzie go obsługujesz. Linia na każdym poziomie stosu wywołań wysyła 3 alerty za 1 awarię.

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

Wynik

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

## Co zapisuje LogBrew

Każdy rekord staje się 1 logiem z poziomem, nazwą loggera, nazwą pliku, funkcją, numerem linii i modułem. Wartości proste z `extra={}` stają się polami, po których filtrujesz, a `metadata={}` na handlerze dodaje pole do każdej linii, jak `service` powyżej.

Przy wyjątku log dostaje `exceptionName` i `exceptionMessage`. Przekaż `include_exception_text=True` do handlera, aby zapisać też tekst tracebacku.

`install_process_error_capture()` zamienia nieprzechwycony wyjątek w problem na poziomie `critical`, z typem wyjątku, ramkami stosu i mechanizmem `python.excepthook`.

## Najczęściej zadawane pytania

### Jaki jest domyślny poziom logowania w Pythonie?

WARNING. Bez wywołania `basicConfig()` logger główny wypisuje WARNING, ERROR i CRITICAL na stderr jako `WARNING:root:message`, a DEBUG i INFO odrzuca.

### Dlaczego logging.basicConfig nic nie robi?

Logger główny ma już handler, z wcześniejszego wywołania `basicConfig()` albo z biblioteki, więc Python ignoruje wywołanie. Przekaż `force=True`, aby zastąpić handlery.

### Czym różni się logging.error od logging.exception?

`log.exception()` to `log.error()` z `exc_info=True`. Loguje na poziomie ERROR i dołącza traceback. Wywołuj go tylko wewnątrz bloku `except`.

### Jakie są poziomy logowania w Pythonie po kolei?

DEBUG 10, INFO 20, WARNING 30, ERROR 40, CRITICAL 50. Logger przepuszcza rekord, gdy jego numer jest równy ustawionemu poziomowi albo wyższy.

### Używać print() czy logging w Pythonie?

Używaj `logging`. `print()` nie ma poziomu, znacznika czasu, nazwy loggera ani handlera. Z `logging` włączasz linie per moduł i wysyłasz je do pliku albo do LogBrew.

## Zobacz każdy wyjątek Pythona z tracebackiem

SDK LogBrew dla Pythona wysyła każdą linię logu z poziomem, loggerem, plikiem i linią, a nieprzechwycony wyjątek zamienia w problem ze śladem stosu. Zacznij od hojnego darmowego planu, bez karty.

[Zacznij za darmo](https://logbrew.co/pl)

## Źródła

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

## Więcej poradników o agentach i Pythonie

- [Dodaj serwer MCP do Claude Code i Codex](https://logbrew.co/pl/guides/mcp-server-claude-code-codex)
- [Jak używać AGENTS.md w Claude Code i Codex](https://logbrew.co/pl/guides/agents-md)
- [Napraw błąd Claude 529 overloaded i błąd 429 rate limit](https://logbrew.co/pl/guides/claude-overloaded-rate-limit-error)
- [Logowanie strukturalne z formatem logów i poziomami, które przeszukasz po polu](https://logbrew.co/pl/guides/structured-logging)
- [Jak naprawić błędy w Claude Code, Codex, JavaScript i Pythonie](https://logbrew.co/pl/guides)
