Każdy programista, niezależnie od doświadczenia, w trakcie tworzenia oprogramowania nieuchronnie spotyka się z błędami. Mogą to być pomyłki w logice, które prowadzą do nieoczekiwanych rezultatów, naruszenia zasad składni języka programowania, problemy pojawiające się podczas uruchamiania programu, i wiele innych. Te niedoskonałości w kodzie są powszechnie nazywane błędami.
Błędy są nieodłączną częścią każdego języka programowania. Nie ma znaczenia, jak prosty i przystępny jest dany język, w każdym z nich istnieje ryzyko popełnienia błędów.
Na przykład, język Python, znany ze swojej czytelności i ekspresyjnej składni, uważany za stosunkowo łatwy do nauki i użytkowania, nie uchroni nas przed popełnianiem błędów programistycznych.
Skoro błędy są nieuniknione, warto zapoznać się z ich różnymi rodzajami i przyczynami powstawania. Pozwoli to na ich unikanie lub minimalizację podczas pisania kodu, a także da wiedzę o tym, jak sobie z nimi radzić, gdy wystąpią.
Poniżej przedstawiamy najczęściej spotykane błędy w Pythonie, na które możesz natrafić podczas programowania:
Błędy składni
Błąd składni pojawia się, kiedy kod narusza reguły języka programowania. Powoduje on, że dana linijka kodu jest niepoprawna.
Przykładowo, w Pythonie, aby wyświetlić tekst, należy go umieścić w cudzysłowie. Pominięcie cudzysłowów spowoduje błąd składni.
Inne przykłady błędów składni to brak nawiasów otwierających lub zamykających (okrągłych, kwadratowych, klamrowych), niepoprawna pisownia słów kluczowych lub nazw funkcji, pominięcie dwukropka na końcu instrukcji warunkowych lub pętli, albo brak wymaganych operatorów w wyrażeniach.
Generalnie, błąd składni występuje, gdy nie stosujemy się do zasad pisania kodu w Pythonie.
## błąd składni wynikający z braku cudzysłowów ## wokół tekstu do wyświetlenia print("Hello World) age = 20 ## błąd składni wynikający z braku dwukropka w instrukcji if if age > 18 print("Age is over 18") ## błąd składni, ponieważ '(' nie zostało zamknięte def square(x: return x * x print(square(4))
Po uruchomieniu powyższego kodu, pojawi się komunikat o błędzie, jak poniżej:
Komunikat o błędzie generowany przy uruchomieniu kodu:
File "/home/madici/Desktop/helloworld.py", line 1 print("Hello World) ^ SyntaxError: unterminated string literal (detected at line 1)
Aby naprawić te błędy, należy użyć poprawnej składni Pythona, jak pokazano niżej:
print("Hello World") age = 20 if age > 18: print("Age is over 18") def square(x): return x * x print(square(4))
Błąd wcięcia
W odróżnieniu od języków takich jak Java, C czy C++, gdzie bloki kodu są wydzielane za pomocą nawiasów klamrowych, Python wykorzystuje wcięcia do określenia hierarchii i struktury kodu. Na przykład, w Javie kod wykonywany po spełnieniu warunku w instrukcji sterującej jest umieszczany w nawiasach klamrowych.
W Pythonie natomiast, blok kodu jest wcięty. Typowe wcięcie składa się z czterech spacji lub jednej tabulacji. Ważne jest, aby liczba spacji była spójna w całym kodzie.
Jako programista Pythona, możesz spotkać się z błędem wcięcia, gdy zapomnisz dodać wymaganego wcięcia (na przykład w instrukcjach sterujących lub funkcjach), gdy używasz jednocześnie tabulacji i spacji (co dezorientuje interpreter), lub gdy wcięcia są niespójne w całym kodzie.
Poniżej znajduje się przykład kodu, który wywołuje błąd wcięcia:
age = 20 if age > 18: print("Age is greater than 18") print("You're allowed to drive") else: print("Age is less than 18")
Komunikaty o błędach, które wynikają z powyższego kodu, przedstawione są poniżej:
Komunikat o błędzie, który pojawi się przy próbie uruchomienia kodu:
File "/home/madici/Desktop/helloworld.py", line 3 print("Age is greater than 18") ^ IndentationError: expected an indented block after 'if' statement on line 2
Aby naprawić błędy, należy dodać wcięcie w wierszu po instrukcji if oraz upewnić się, że jest ono zgodne z wcięciami w pozostałej części kodu, jak pokazano poniżej:
age = 20 if age > 18: print("Age is greater than 18") print("You're allowed to drive") else: print("Age is less than 18")
Błąd typu
W Pythonie, `TypeError` to wyjątek, który występuje, gdy próbujesz wykonać operację z użyciem niezgodnego typu danych. Na przykład, próba dodania tekstu i liczby całkowitej, lub próba połączenia tekstu z liczbą całkowitą, spowoduje wystąpienie błędu `TypeError`.
Błędy typu mogą również pojawić się, gdy używasz funkcji lub metod z nieprawidłowymi typami danych, gdy próbujesz uzyskać dostęp do elementów w strukturze danych (np. w liście) za pomocą indeksu, który nie jest liczbą całkowitą, lub gdy próbujesz iterować po obiekcie, który nie obsługuje iteracji.
Generalnie, każda operacja, która używa niepoprawnego typu danych, doprowadzi do błędu `TypeError`.
Poniżej przedstawiono przykłady operacji, które mogą powodować błędy typu:
# Błąd typu wynikający z łączenia tekstu z liczbą całkowitą age = 25 message = "I am " + age + " years old." list1 = [1, "hello", 5, "world", 18, 2021] #Błąd typu wynikający z niewłaściwego użycia metod print(sum(list1)) #Błąd typu wynikający z dodawania tekstu i liczby num1 = 10 num2 = "16" print(num1 + num2) #Błąd typu wynikający z użycia indeksu niebędącego liczbą całkowitą list2 = ["hello", "from", "the", "other", "side"] print(list2["1"])
Komunikaty o błędach, które generuje powyższy kod, przedstawione są poniżej:
Przykładowy komunikat o błędzie `TypeError` z powyższego kodu:
File "/home/madici/Desktop/helloworld.py", line 3, in <module> message = "I am " + age + " years old." ~~~~~~~~^~~~~ TypeError: can only concatenate str (not "int") to str
Aby usunąć błędy, użyj poprawnego typu danych lub dokonaj konwersji typów, jak pokazano poniżej:
age = 25 message = "I am " + str(age) + " years old." list1 = [1, 5, 18, 2021] print(sum(list1)) num1 = 10 num2 = "16" print(num1 + int(num2)) list2 = ["hello", "from", "the", "other", "side"] print(list2[1])
Błąd atrybutu
W Pythonie `AttributeError` pojawia się, gdy próbujesz użyć atrybutu, który nie istnieje w danym obiekcie, lub gdy próbujesz wywołać metodę, która nie jest zdefiniowana dla tego obiektu. `AttributeError` informuje, że dany obiekt nie ma atrybutu ani metody, której próbujesz użyć.
Na przykład, jeśli wywołasz metodę łańcuchową na liczbie całkowitej, pojawi się `AttributeError`, ponieważ metoda nie istnieje dla typu obiektu, dla którego ją wywołujesz.
W przykładzie poniżej metoda `capitalize()`, która służy do zmiany pierwszej litery łańcucha na wielką, jest wywoływana na liczbie całkowitej. Wynikiem jest błąd atrybutu, ponieważ typ `int` nie posiada metody `capitalize()`.
# AttributeError wynikający z wywołania capitalize() na liczbie całkowitej num = 1445 cap = num.capitalize() print(cap)
Uruchomienie tego kodu spowoduje wyświetlenie komunikatu o błędzie, jak poniżej:
Komunikat `AttributeError` z powyższego kodu:
File "/home/madici/Desktop/helloworld.py", line 3, in <module> cap = num.capitalize() ^^^^^^^^^^^^^^ AttributeError: 'int' object has no attribute 'capitalize'
Aby rozwiązać problem `AttributeError`, upewnij się, że wywoływana metoda lub atrybut rzeczywiście istnieje w obiekcie, dla którego jest wywoływana. W tym przypadku, wywołanie metody `capitalize()` dla łańcucha znaków rozwiązuje problem, jak poniżej:
Błąd importu
`ImportError` w Pythonie występuje, gdy próbujesz zaimportować moduł, który nie może zostać znaleziony lub nie jest dostępny w bieżącym środowisku. Przyczyny to: brak zainstalowania modułu, niepoprawna konfiguracja ścieżki dostępu do modułu lub błędna pisownia nazwy modułu, który próbujesz zaimportować.
`ImportError` ma podklasę o nazwie `ModuleNotFoundError`, która jest generowana, gdy nie można odnaleźć modułu.
Na przykład, kod, który próbuje zaimportować bibliotekę `pandas` do analizy danych, wygeneruje błąd, ponieważ moduł nie jest zainstalowany.
Komunikat błędu `ImportError`:
File "/home/madici/Desktop/helloworld.py", line 1, in <module> import pandas ModuleNotFoundError: No module named 'pandas'
Aby rozwiązać ten błąd, upewnij się, że moduł, który chcesz zaimportować, został zainstalowany. Jeśli to nie rozwiąże problemu, sprawdź, czy poprawnie wpisałeś nazwę modułu i czy ścieżka do niego jest prawidłowa.
Błąd wartości
Jest to wyjątek, który pojawia się, gdy funkcja w Pythonie otrzyma wartość prawidłowego typu, ale sama wartość jest nieprawidłowa. Na przykład, funkcja `math.sqrt()`, która służy do obliczania pierwiastka kwadratowego, zwróci błąd wartości, jeśli podasz jej liczbę ujemną.
O ile wartość będzie odpowiedniego typu (wartość numeryczna), o tyle wartość ujemna sprawi, że stanie się nieodpowiednia dla tej funkcji.
Funkcja `int()`, która konwertuje liczbę lub tekst na liczbę całkowitą, zwróci błąd wartości, jeśli przekażesz tekst, który nie jest liczbą. Przekazanie „123” lub „45” nie spowoduje błędu, ponieważ te teksty mogą zostać przekonwertowane na liczbę całkowitą.
Jeśli jednak przekażesz tekst, który nie jest liczbą, na przykład „Hello”, otrzymasz `ValueError`. Dzieje się tak dlatego, że „Hello”, mimo bycia tekstem, nie ma odpowiednika w postaci liczby całkowitej.
Poniższy przykład kodu generuje `ValueError`:
# Błąd wartości wynikający z nieodpowiedniej wartości w funkcji sqrt() import math num = -64 root = math.sqrt(num) print(root) # Błąd wartości wynikający z przekazania tekstu bez odpowiednika w postaci liczby całkowitej do funkcji int() numString = "Hello" num = int(numString) print(num)
Błędy z powyższego kodu przedstawione są poniżej:
Komunikat o błędzie:
File "/home/madici/Desktop/helloworld.py", line 4, in <module> root = math.sqrt(num) ^^^^^^^^^^^^^^ ValueError: math domain error
Aby naprawić błąd, należy użyć odpowiednich wartości w funkcjach, jak pokazano poniżej:
import math num = 64 root = math.sqrt(num) print(root) numString = "5231" num = int(numString) print(num)
Błąd wejścia/wyjścia
Błąd `IOError` (Input/Output Error) to wyjątek, który występuje w przypadku niepowodzenia operacji wejścia lub wyjścia. Może to być spowodowane próbą otwarcia pliku, który nie istnieje, brakiem miejsca na dysku, próbą uzyskania dostępu do pliku bez odpowiednich uprawnień, lub próbą otwarcia pliku, który jest używany przez inną operację.
Metody takie jak `open()`, `read()`, `write()` i `close()`, które są używane podczas pracy z plikami, mogą wywołać ten błąd.
Rozważmy poniższy kod, który próbuje otworzyć plik o nazwie „notes.txt”, który nie istnieje. Kod wywoła błąd `IOError`, który jest reprezentowany przez `FileNotFoundError`:
Z następującym komunikatem o błędzie:
File "/home/madici/Desktop/helloworld.py", line 2, in <module> file1 = open("notes.txt", "r") ^^^^^^^^^^^^^^^^^^^^^^ FileNotFoundError: [Errno 2] No such file or directory: 'notes.txt'
Aby uniknąć powyższego błędu, należy upewnić się, że plik „notes.txt” istnieje w katalogu, z którego uruchamiasz program. Innym sposobem obsługi błędów `IOError` jest użycie bloku `try…except`, jak pokazano poniżej:
Błąd nazwy
Błąd `NameError` to wyjątek, który pojawia się podczas próby użycia zmiennej, funkcji lub modułu, który nie istnieje, nie jest zdefiniowany w bieżącym zakresie lub nie ma przypisanej wartości.
Błąd ten zazwyczaj występuje, gdy popełnisz literówkę w nazwie zmiennej lub funkcji, lub użyjesz jej przed zdefiniowaniem. Użycie modułu bez jego zaimportowania również spowoduje `NameError`.
Poniższy kod spowoduje wystąpienie `NameError`:
# Błąd nazwy wynika z braku zaimportowanego modułu math num = 64 root = math.sqrt(64) print(root) # Błąd nazwy wynika z użycia x przed zdefiniowaniem y = 23 print(x) #Błąd nazwy, ponieważ funkcja great nie została zdefiniowana def greet(): print("Good morning") great()
Poniższe komunikaty o błędach wynikają z powyższego kodu:
Przykładowy komunikat `NameError`:
File "/home/madici/Desktop/helloworld.py", line 3, in <module> root = math.sqrt(64) ^^^^ NameError: name 'math' is not defined
Aby rozwiązać ten błąd, upewnij się, że nie używasz modułów przed ich zaimportowaniem, nie używasz zmiennych lub funkcji przed ich zdefiniowaniem, i że nie popełniłeś literówki w nazwach funkcji lub zmiennych:
import math num = 64 root = math.sqrt(64) print(root) y = 23 print(y) def greet(): print("Good morning") greet()
Błąd indeksu
Błąd `IndexError` to wyjątek, który występuje, gdy próbujesz uzyskać dostęp do elementu listy lub krotki za pomocą indeksu, który wykracza poza zakres. Rozważ poniższą listę:
list1 = [1, 2, 3, 4, 5]
Lista zawiera pięć elementów. Indeksy w Pythonie są liczone od zera. Dlatego lista powyżej ma zakres indeksów od 0 do n-1, gdzie n jest liczbą elementów. W tym przypadku zakres indeksów to 0 do 4.
Jeśli spróbujesz uzyskać dostęp do elementu o indeksie większym niż 4, wystąpi błąd `IndexError`, ponieważ ten indeks jest poza zakresem listy. Poniższy kod generuje błąd `IndexError`:
list1 = [1, 2, 3, 4, 5] item = list1[6] #IndexError, ponieważ indeks jest poza zakresem print(item)
Błąd wynikający z powyższego kodu przedstawiono poniżej:
Komunikat błędu:
File "/home/madici/Desktop/helloworld.py", line 2, in <module> item = list1[6] #IndexError because the list index is out of range ~~~~~^^^ IndexError: list index out of range
Najlepszym sposobem na uniknięcie błędu `IndexError` jest użycie funkcji `range()` i `len()`, aby upewnić się, że uzyskujesz dostęp tylko do elementów, które znajdują się w poprawnym zakresie:
list1 = [1, 2, 3, 4, 5] for i in range(len(list1)): print(list1[i])
Błąd klucza
Błąd `KeyError` to wyjątek, który pojawia się, gdy próbujesz uzyskać dostęp do elementu słownika za pomocą klucza, który nie istnieje w tym słowniku. Rozważ poniższy słownik:
cities = {"Canada": "Ottawa", "USA": "Washington", "Italy": "Rome"}
Klucze w słowniku to „Canada”, „USA”, „Italy”. Za pomocą tych kluczy możesz uzyskać dostęp do odpowiednich wartości w słowniku. Jeśli jednak spróbujesz uzyskać dostęp do elementu za pomocą klucza, który nie istnieje, na przykład „Brazil”, wystąpi błąd klucza `KeyError`, jak pokazano poniżej:
Komunikat błędu `KeyError`:
File "/home/madici/Desktop/helloworld.py", line 6, in <module> print(cities["Brazil"]) ~~~~~~^^^^^^^^^^ KeyError: 'Brazil'
Aby rozwiązać problem `KeyError`, upewnij się, że klucze, których używasz do uzyskania dostępu do elementów w słowniku, faktycznie w nim istnieją. Możesz to zrobić, używając instrukcji `if…else`, jak poniżej:
cities = {"Canada": "Ottawa", "USA": "Washington", "Italy": "Rome"} country = "Canada" if country in cities: print("The capital city of " + country + " is " + cities[country]) else: print("The key " + country + " is not present in the cities dictionary")
W ten sposób unikniesz błędu `KeyError` podczas uzyskiwania dostępu do elementów ze słownika.
Podsumowanie
Podczas kodowania w Pythonie, niezależnie od poziomu Twojej wiedzy, na pewno natkniesz się na błędy. Dlatego ważne jest, aby zapoznać się z różnymi rodzajami błędów, które zostały omówione w artykule, aby wiedzieć, jak sobie z nimi radzić, gdy się pojawią.
Warto również zapoznać się z przydatnymi, jedno-linijkowymi rozwiązaniami w Pythonie, które mogą uprościć wykonywanie typowych zadań.