Logowanie i debugowanie w Pythonie – diagnozuj problemy jak profesjonalista

Kacper Sieradziński
Kacper Sieradziński
13 marca 2025Edukacja4 min czytania

Każdy programista zna ten moment: wszystko wygląda dobrze, a mimo to coś nie działa. Kod poprawny, testy przechodzą, a aplikacja po prostu robi coś… dziwnego. To wtedy zaczyna się prawdziwa robota – diagnozowanie problemu. I właśnie tu wchodzą do gry dwa narzędzia, które odróżniają początkującego od zawodowca: logowaniedebugowanie.

Obraz główny Logowanie i debugowanie w Pythonie – diagnozuj problemy jak profesjonalista

Logowanie – twoje oczy wewnątrz aplikacji

Kod bez logowania to jak samolot bez czujników. Dopóki lecisz prosto, jest dobrze. Ale gdy zaczyna się turbulencja, nie wiesz nawet, co się dzieje. Logi to twój rejestr lotu – zapis wszystkiego, co dzieje się w aplikacji, w kolejności, w jakiej to następuje.

W Pythonie logowanie jest banalne do wdrożenia, a potrafi zaoszczędzić godziny frustracji. Najprostszy przykład:

Python
1 2 3 4 5 6 7 8 9 10 11 import logging logging.basicConfig( level=logging.INFO, format="%(asctime)s [%(levelname)s] %(name)s: %(message)s" ) logger = logging.getLogger(__name__) logger.info("Aplikacja wystartowała") logger.warning("Brak połączenia z bazą danych – próba ponowienia") logger.error("Nie udało się pobrać danych z API", exc_info=True)

To, co wydaje się prostym komunikatem, w praktyce staje się twoim największym sojusznikiem w walce z błędami. Dzięki odpowiednim poziomom logów (DEBUG, INFO, WARNING, ERROR, CRITICAL) możesz dokładnie sterować tym, ile informacji widzisz.

Na środowisku developerskim chcesz mieć pełen obraz – dlatego używaj DEBUG. Na produkcji? Tylko to, co istotne: INFO lub wyżej. Logi w trybie debugowym potrafią być gigantyczne, a przeglądanie tysięcy linii „szumu” to strata czasu.

Struktura logów ma znaczenie

Nie chodzi tylko o to, co logujesz, ale jak. Log, który nie ma kontekstu, jest bezużyteczny. Dobry log powinien zawierać:

  • czas zdarzenia (najlepiej w UTC),
  • poziom logu,
  • nazwę modułu lub klasy,
  • komunikat z opisem,
  • opcjonalnie traceback, jeśli doszło do wyjątku.

Jeśli piszesz większe aplikacje, przestań myśleć o logach jak o „zwykłym tekście". To dane. Możesz je analizować, filtrować i przeszukiwać. Zamiast plików tekstowych, wyślij logi do systemu typu ELK Stack (Elasticsearch, Logstash, Kibana) lub Grafana Loki. Wtedy diagnozowanie błędów staje się kwestią sekund.

Rotacja logów – żeby nie zabiły własnego serwera

Logi mają jedną wadę: rosną. Jeśli nie zadbasz o ich rotację, mogą zapełnić dysk. W Pythonie masz gotowe rozwiązania:

Python
1 2 3 4 5 6 from logging.handlers import TimedRotatingFileHandler handler = TimedRotatingFileHandler( "app.log", when="midnight", interval=1, backupCount=7, encoding="utf-8" ) logger.addHandler(handler)

Taki zapis utworzy nowy plik logu co północ, zachowa historię z ostatnich siedmiu dni i automatycznie usunie starsze pliki.

W systemach kontenerowych (Docker, Kubernetes) nie zapisuj logów do plików – kieruj je na stdout, a zbieraj centralnie. Dzięki temu masz pełną historię działania wszystkich kontenerów w jednym miejscu.

Debugowanie – chirurgiczna precyzja

Debugowanie to moment, w którym zatrzymujesz kod i patrzysz mu w oczy. Zamiast zgadywać, co mogło pójść źle, po prostu sprawdzasz, co się dzieje naprawdę.

Początkujący programiści nadużywają print(). To szybkie, tanie i czasem skuteczne, ale gdy projekt rośnie, print() staje się śmieciem w kodzie. Profesjonalista używa debuggera.

W Pythonie masz kilka możliwości:

  • moduł pdb (standardowy debugger z konsoli),

  • debugpy (działa z VS Code),

  • wbudowany debugger w PyCharm, który pozwala krokować kod, podglądać zmienne i wykonywać linie w locie.

Zasada jest prosta: breakpoint zamiast printa. Ustawiasz punkt zatrzymania, uruchamiasz program w trybie debugowania i obserwujesz, co dzieje się w środku.

Technika binary search w debugowaniu

Kiedy nie wiesz, gdzie leży problem, nie próbuj analizować wszystkiego. Zastosuj strategię dziel i rządź. Ustal fragment kodu, w którym może być błąd, a następnie:

  1. Ustaw breakpoint w połowie tego obszaru.

  2. Jeśli do tego miejsca wszystko działa – przesuwaj się dalej.

  3. Jeśli nie działa – cofnij się.

  4. Powtarzaj, aż znajdziesz dokładną linię, która psuje logikę.

To nie magia, to matematyka. Dzięki temu zamiast 200 linii, analizujesz 10.

Analiza wyjątków i tracebacków

Traceback to twoja mapa błędu. Czytaj ją zawsze od dołu do góry – tam znajduje się pierwotna przyczyna. Większość programistów popełnia błąd, analizując pierwszy wiersz błędu, który często mówi tylko, że „coś się popsuło w aplikacji". Prawdziwy winowajca zwykle siedzi kilka linijek niżej.

Jeśli chcesz, by Python sam zapisał traceback w logach, dodaj exc_info=Truelogger.error(). To prosty sposób, by nigdy nie zgubić kontekstu błędu.

Dobre praktyki

Pisząc logi, pamiętaj o kilku zasadach, które odróżniają zawodowca od amatora:

  • Loguj kontekst – kto, co, na jakich danych i w jakim momencie.

  • Nie loguj danych wrażliwych: haseł, tokenów, maili użytkowników.

  • Stosuj spójny format, najlepiej JSON, jeśli analizujesz logi w systemach monitorujących.

  • Zawsze oznaczaj wersję aplikacji i środowisko (np. prod, staging).

  • W testach automatycznych ogranicz logi do WARNING i wyżej, by nie tonąć w detalach.

  • Po wdrożeniu monitoruj logi aktywnie – nie czekaj, aż użytkownik zgłosi błąd.

Podsumowanie

Profesjonalny programista nie polega na szczęściu. Tworzy kod, który można obserwować, diagnozować i naprawiać bez zgadywania.

  • Logowanie daje Ci wgląd w przeszłość.

  • Debugowanie pozwala zajrzeć w teraźniejszość.

Razem tworzą zestaw narzędzi, dzięki któremu przestajesz być „gaszącym pożary", a stajesz się inżynierem, który wie, co się dzieje w jego systemie.

Jeśli Twoja aplikacja milczy, gdy coś idzie nie tak – to nie jest oznaka stabilności. To oznaka ślepoty. Naucz ją mówić, zanim będzie za późno.