Czytanie i rozumienie Tracebacka to codzienność w pracy z Pythonem. Niezależnie od tego, czy czyścisz dane, czy odpalasz kontener na serwerze, czerwony blok logów zwykle zawiera wszystkie potrzebne wskazówki.
Poniżej zebraliśmy najczęstsze typy błędów z praktyki, pogrupowane nie alfabetycznie, ale według kontekstu: od problemów środowiskowych, przez składnię i typy danych, po limity zasobów i błędy stricte biznesowe.
I. Środowisko i zależności
Ten zestaw błędów pojawia się najczęściej po ściągnięciu nowego projektu, zmianie środowiska albo przy budowaniu obrazów Dockera. Kod może być poprawny – to środowisko nie jest jeszcze gotowe.
1. ModuleNotFoundError / ImportError
Typowa sytuacja: moduł zewnętrzny lub własny pakiet nie daje się zaimportować.
- czy na pewno aktywowałeś właściwe virtualenv?
- czy
requirements.txtzostał zainstalowany w tym środowisku? - czy katalog z własnym modułem jest w
sys.path?
# w aktywnym virtualenv
pip install requests
import sys
sys.path.append("/path/to/module_directory")
import some_custom_module
2. FileNotFoundError
Zwykle wychodzi na jaw dopiero w środowisku innym niż lokalne – gdy ścieżki względne rozumiane są inaczej niż na Twojej maszynie. Tam, gdzie to możliwe, korzystaj z absolutnych ścieżek lub buduj je względem katalogu projektu.
II. Składnia i zasięg zmiennych
W dobrym IDE większość takich błędów zobaczysz jeszcze przed uruchomieniem skryptu. Gdy jednak edytujesz plik na serwerze w prostym edytorze, łatwo o wpadkę.
SyntaxError i IndentationError
Brak dwukropka, niezamknięty nawias, mieszanie spacji z tabami – Python jest bardzo wrażliwy na poprawną strukturę kodu. Warto trzymać się konwencji 4 spacji na poziom wcięcia i używać autoformatowania (Black, Ruff itd.).
NameError i UnboundLocalError
Pierwszy pojawia się, gdy odwołujesz się do nazwy, która nie istnieje w danym zasięgu. Drugi – gdy interpreter uznaje, że tworzysz zmienną lokalną, ale próbujesz jej użyć, zanim zostanie przypisana.
x = 20
def test_function():
# Bez global x poniżej Python uzna x za zmienną lokalną
global x
print(x)
x = 10
test_function()
III. Dane i typy: błędy przy pracy z wejściem
Tu najczęściej potykamy się przy integracjach z API, parsowaniu JSON-ów czy sprzątaniu danych analitycznych.
TypeError i ValueError
TypeError oznacza, że operujemy na niekompatybilnych typach
(np. dodawanie str + int albo próba wywołania
liczby jak funkcji). ValueError pojawia się, gdy typ niby pasuje,
ale wartość nie – np. konwersja nienumerycznego napisu na int.
try:
num = int("abc")
except ValueError:
print("Nie udało się przekształcić na liczbę całkowitą")
IndexError i KeyError
Pierwszy oznacza wyjście poza zakres listy, drugi – brak klucza w słowniku.
Przy danych z zewnątrz lepiej używać dict.get() z wartością
domyślną niż zakładać, że klucz zawsze istnieje.
my_dict = {"a": 1, "b": 2}
print(my_dict.get("c", 0)) # brak KeyError, zwraca 0
AttributeError
Próba użycia atrybutu lub metody, której obiekt nie posiada
(np. lista z .add() zamiast .append()).
Zwykle oznacza to błędne założenie co do typu obiektu zwracanego przez inną funkcję.
UnicodeDecodeError
Pojawia się przy czytaniu tekstu w innym kodowaniu niż domyślne. Rozwiązanie: jawnie wskazać encoding.
byte_data = b"\xd0\xbf\xd1\x80\xd0\xb8..."
text = byte_data.decode("utf-8")
IV. Limity zasobów i obliczeń
Gdy operujesz na dużych zbiorach danych, rekurencji lub ekstremalnych wartościach, wchodzą do gry ograniczenia pamięci i stosu.
MemoryError
Oznacza najczęściej próbę wczytania do pamięci zbyt dużej struktury danych. W praktyce lepiej przetwarzać dane strumieniowo (generatory, chunkowanie) zamiast budować gigantyczne listy.
# zamiast: huge_list = [i for i in range(10**10)]
huge_generator = (i for i in range(10**10))
RecursionError
Python ma domyślny limit głębokości rekurencji (~1000). Można go podnieść
przez sys.setrecursionlimit(), ale znacznie lepszym rozwiązaniem
jest przepisanie algorytmu na wersję iteracyjną.
OverflowError i ZeroDivisionError
W czystym Pythonie liczby całkowite są"bez limitu”, ale w bibliotekach opartych na C
(NumPy itd.) typy takie jak int32/int64 mają swój sufit.
ZeroDivisionError to z kolei klasyka – dzielenie przez zero.
V. Logika biznesowa i błędy wykonywania
AssertionError
Zwykle pojawia się podczas developmentu, gdy używasz assert, aby
upewnić się, że"to nigdy nie powinno się wydarzyć”. W produkcji możesz włączyć
Pythona z -O, żeby zignorować asercje dla niewielkiego zysku
wydajności.
RuntimeError
Gdy nie ma lepszego, bardziej precyzyjnego typu wyjątku, wiele bibliotek
używa RuntimeError jako"ogólnego” sygnału, że coś poszło nie tak
w logice wykonania (np. nieoczekiwany stan maszyny).
VI. Trzy pytania kontrolne na koniec
-
Czy na pewno jesteś w tym virtualenv?
PrzyModuleNotFoundErrorzanim zrobisz kolejnepip install, sprawdź, czy interpreter w IDE/terminalu to ten sam, do którego instalowałeś paczki. -
Czy kod zakłada, że dane z zewnątrz są"idealne”?
Z API lub plików zawsze może przyjśćnull, zły format lub brak klucza – używaj.get(),try/except ValueErrori sensownych domyślnych wartości. -
Czytasz Traceback od dołu?
Górne linie często należą do frameworka. Prawdziwa przyczyna i numer linii Twojego kodu zwykle siedzą w ostatnich linijkach Tracebacka.