Ten samouczek wyjaśnia obsługę wyjątków w Pythonie za pomocą bloku Try Except z pomocą przykładów programowania:
Dwa typy błędów mogą spowodować nagłe zatrzymanie programu Python, tj. Błędy składni oraz Wyjątki W tym samouczku omówimy drugi typ błędu (wyjątki) w ramach kilku ważnych tematów.
Wiele skorzystamy na obsłudze wyjątków w naszej aplikacji, takich jak:
- Tworzenie solidnej aplikacji.
- Tworzenie czystego i wolnego od błędów kodu.
Python Try Except
Dobrą wiadomością jest to, że Python posiada sporą liczbę wbudowanych wyjątków do wychwytywania błędów w naszym kodzie. Daje nam również możliwość tworzenia niestandardowych wyjątków, gdy żaden z wbudowanych wyjątków nie odpowiada naszym potrzebom.
Co to jest wyjątek?
Czym więc jest wyjątek w Pythonie? Cóż, w prostych słowach, za każdym razem, gdy interpreter Pythona próbuje wykonać nieprawidłowy kod, zgłasza wyjątek, a w przypadkach, gdy taki wyjątek nie jest obsługiwany, zakłóca normalny przepływ instrukcji programu i drukuje traceback.
Stwórzmy nieprawidłowy kod i zobaczmy, jak zareaguje interpreter Pythona.
Otwórz powłokę Pythona i uruchom następujący kod.
>>> 50/0
Jest to jeden z najczęstszych błędów w programowaniu. Powyższy kod próbuje podzielić liczbę 50 przez 0 (Interpreter Pythona postrzega to jako nieprawidłową operację i zgłasza błąd ZeroDivisionError , przerywa działanie programu i wypisuje błąd.
Widzimy wyraźnie, że ZeroDivisionError to wyjątek, który został zgłoszony. Jest to rzeczywiście własny sposób Pythona, aby powiedzieć nam, że dzielenie liczby przez zero nie jest fajne. Chociaż w innych językach, takich jak JavaScript, nie jest to błąd; a Python surowo zabrania tej praktyki.
Ważne jest również, aby wiedzieć, że jest to tylko obiekt wyjątku, a Python ma wiele takich obiektów wbudowanych. Sprawdź oficjalną dokumentację Pythona, aby zobaczyć wszystkie wbudowane wyjątki Pythona.
Zrozumienie Traceback
Zanim przejdziemy do obsługi wyjątków, myślę, że pomocne będzie zrozumienie, co dokładnie się stanie, jeśli wyjątki nie zostaną obsłużone i w jaki sposób Python robi wszystko, co w jego mocy, aby poinformować nas o błędzie.
Za każdym razem, gdy Python napotyka błąd, zgłasza wyjątek. Jeśli wyjątek ten nie zostanie obsłużony, generuje pewne informacje zwane Traceback. Jakie informacje zawiera ten traceback?
Zawiera:
- Komunikat o błędzie, który mówi nam, jaki wyjątek został zgłoszony i co się stało przed jego zgłoszeniem.
- Różne numery linii kodu, które spowodowały ten błąd. Błąd może być spowodowany przez sekwencję wywołań funkcji o nazwie stos wywołań które omówimy później.
Chociaż jest to nieco zagmatwane, obiecujemy, że następny przykład przyniesie więcej światła na nasze zrozumienie.
Przypomnijmy sobie traceback, który został wydrukowany z dzielenia 50 przez 0 powyżej, widzimy, że traceback zawiera następujące informacje:
- Plik "": Mówi nam to, że ten kod został uruchomiony z terminala konsoli.
- linia 1: Mówi nam, że błąd wystąpił w tym numerze linii.
- ZeroDivisionError: podział według zero: Informuje nas, jaki wyjątek został zgłoszony i co go spowodowało.
Wypróbujmy inny przykład i zobaczmy, w jaki sposób stos wywołań Otwórz edytor, wprowadź poniższy kod i zapisz jako tracebackExp .py
def stack1(numb): # 1 div = 0 # 2 stack2(numb, div) # 3 def stack2(numb, div): # 5 compute = numb/div # 6 print(compute) # 7 if __name__ == '__main__': # 9 numb = 5 # 10 stack1(numb) # 11
Otwórz terminal w katalogu, w którym znajduje się ten plik i uruchom go.
python tracebackExp.py
Zostanie wyświetlony następujący komunikat zwrotny:
Powyższy traceback może wydawać się mylący, ale tak naprawdę nie jest. Pythonistas wymyślili najlepszy sposób na odczytanie tracebacku, który pochodzi od od dołu do góry Wykorzystajmy więc tę mądrość, aby spróbować zrozumieć, co ten traceback ma do zaoferowania.
- W dolnej części otrzymujemy informację o wyjątku, który został zgłoszony i jego przyczynie.
- Przechodząc wyżej, otrzymujemy nazwę pliku tracebackExp .py, w którym wystąpił ten błąd, obliczenie, które spowodowało ten błąd compute = numb/div, funkcja stack2 oraz numer łącza w linii 6, w której wykonano to obliczenie.
- Przechodząc wyżej, widzimy, że nasza funkcja stack2 została wywołana w funkcji stack1 w linii numer 3.
- Przechodząc do najwyższego, widzimy, że funkcja stack1 została wywołana w linii numer 11. < moduł > mówi nam, że to plik jest wykonywany.
Typowe wyjątki Pythona
Biblioteka Pythona definiuje bardzo wiele wbudowanych wyjątków. Możesz sprawdzić dokumentację Pythona lub wywołać wbudowaną funkcję lokalny () jak poniżej:
>>> dir(locals()['__builtins__'])
Nie będziemy starali się omówić wszystkich tych wyjątków, ale przyjrzymy się kilku typowym wyjątkom, na które prawdopodobnie się natkniesz.
#1) TypeError
Jest on zgłaszany, gdy operacja lub funkcja zostanie zastosowana do obiektu nieodpowiedniego typu.
Przykład 1
Rozważmy poniższy program, który pobiera dzielną i dzielnik, a następnie oblicza i drukuje wynik dzielenia dzielnej przez dzielnik.
def compute_division(): dividend = int(input("Wprowadź dywidendę: ")) # cast string to int divisor = input("Wprowadź dzielnik: ") # no casting # compute division result = dividend/divisor # print result print("Wynikiem {}/{} jest: {}".format(dividend, divisor, result)) if __name__ == '__main__': result = compute_division()
Żądamy wartości dzielnej i dzielnika od użytkownika, ale zapominamy o rzutowaniu wartości łańcuchowej dzielnika na liczbę całkowitą. Tak więc typem dzielnika jest liczba całkowita( int ) i dzielnikiem typu string( str Następnie otrzymujemy TypeError ponieważ operator dzielenia (/) nie działa na łańcuchach.
Być może zainteresuje Cię fakt, że w przeciwieństwie do Pythona, Javascript posiada Type Coercion, który zasadniczo konwertuje jeden z typów operandu na równoważną wartość typu drugiego operandu, gdy operandy są różnych typów.
#2) ValueError
Jest on zgłaszany, gdy operacja lub funkcja otrzymuje argument, który ma prawidłowy typ, ale nieodpowiednią wartość.
Przykład 2
Rozważmy nasz program w Przykład 1 powyżej.
Jeśli użytkownik wprowadzi wartość alfanumeryczną dla dywidendy, taką jak "3a", nasz program zgłosi wyjątek ValueError. Dzieje się tak, ponieważ chociaż metoda Python int() przyjmuje dowolną liczbę lub ciąg znaków i zwraca obiekt całkowity, wartość ciągu znaków nie powinna zawierać liter ani żadnych wartości nienumerycznych.
#3) AttributeError
Wyjątek ten jest zgłaszany podczas przypisywania lub odwoływania się do atrybutu, który nie istnieje.
Przykład 3
Rozważmy poniższy program, który pobiera liczbę i oblicza jej pierwiastek kwadratowy przy użyciu modułu matematycznego Pythona
import math # import biblioteki math, aby uzyskać dostęp do jej kodu def compute_square_root(number): # obliczenie pierwiastka kwadratowego przy użyciu biblioteki math result = math.sqr(number) return result if __name__ == '__main__': # pobranie danych wejściowych do obliczeń od użytkownika number = int(input("Oblicz pierwiastek kwadratowy z: ")) # wywołanie funkcji do obliczenia pierwiastka kwadratowego
Kiedy użytkownik wprowadza liczbę, nasz program próbuje użyć funkcji z modułu matematycznego do obliczenia jej pierwiastka kwadratowego, ale właśnie w tym miejscu popełniliśmy błąd. Zamiast sqrt omyłkowo wpisaliśmy sqr, który nie istnieje w module matematycznym.
Próbowaliśmy więc odwołać się do atrybutu sqr, który nie istnieje, co doprowadziło do podniesienia wyjątku AttributeError. Większość z nas często popełnia tego rodzaju błędy, więc nie jesteś sam.
Obsługa wyjątków za pomocą Try Except
Jako programista, jedną z rzeczy, na które większość z nas poświęca swój czas, jest pisanie solidnego i odpornego kodu. Kodu, który nie zepsuje się z powodu pewnych błędów. W Pythonie możemy to osiągnąć, zamykając nasze instrukcje wewnątrz próba - z wyjątkiem oświadczenie.
Instrukcja try-except języka Python
Instrukcja try-except ma następującą strukturę:
try: #your code goes here except """Specify exception type(s) here"": #handle exception here
Zamknijmy kod w tracebackExp .py wewnątrz instrukcji try-except.
def stack1(numb): # 1 div = 0 # 2 stack2(numb, div) # 3 def stack2(numb, div): # 5 try: # 6 compute = numb/div # 7 print(compute) # 8 except ZeroDivisionError as zde: # 9 print(zde) # 10 if __name__ == '__main__': # 12 numb = 5 # 13 stack1(numb) # 14 print("program ciągły") # 15
Uruchomienie tego kodu da wynik
W ten sposób działa instrukcja try-except. Python wykonuje kod w bloku try linia 7-8 Jeśli nie zostanie znaleziony nieprawidłowy kod, wówczas kod w bloku except linia 10 jest pomijana i wykonywanie jest kontynuowane.
Jeśli jednak zostanie znaleziony nieprawidłowy kod, wykonanie natychmiast zatrzyma się w bloku try i sprawdzi, czy zgłoszony wyjątek jest zgodny z tym, który podaliśmy w instrukcji except linia 9 Jeśli pasuje, blok except jest wykonywany i kontynuowany. Jeśli nie, program zostanie przerwany.
Blok try zazwyczaj zawiera kod, który może zgłosić wyjątek, podczas gdy blok except wyłapuje i obsługuje wyjątek.
Obsługa wielu wyjątków za pomocą Except
Możemy obsługiwać wiele wyjątków za pomocą pojedynczego "except" lub wielu "excepts". Wszystko zależy od tego, jak chcesz obsługiwać każdy wyjątek.
#1) Obsługa wielu wyjątków za pomocą jednego wyjątku
try: #your code goes here except(Exception1[, Exception2[,...ExceptionN]]]): #handle exception here
Ta metoda jest używana, gdy podejrzewamy, że nasz kod może zgłaszać różne wyjątki i chcemy podjąć tę samą akcję w każdym przypadku. Tak więc, jeśli interpreter Pythona znajdzie dopasowanie, wówczas kod zapisany w bloku except zostanie wykonany.
Rozważmy poniższy przykładowy kod Pythona
def get_fraction(value, idx): arr = [4,5,2,0] # lista liczb idx_value = arr[idx] # if idx is> arr length, IndexError will be raised value/idx_value # if idx_value == 0, ZeroDivisionError will be raised if __name__ =='__main__': # set 'value' and 'idx' value = 54 idx = 3 # call function in a try-except statement. try: result = get_fraction(value, idx) print("Fraction is ", result) except(IndexError, ZeroDivisionError) as ex: print(ex)
Istnieją dwa możliwe wyjątki, które można tu podnieść, ZeroDivisionError i IndexError Jeśli którykolwiek z tych wyjątków zostanie podniesiony, blok except zostanie wykonany.
W powyższym kodzie idx=3, więc idx_ wartość staje się 0 i wartość /idx_ wartość zgłosi błąd ZeroDivisionError
#2) Obsługa wielu wyjątków za pomocą wielu wyjątków
try: #your code goes here except Exception1: #handle exception1 here except Exception2: #handle exception2 here except ExceptionN: #handle exceptionN here
Jeśli wolimy obsługiwać każdy wyjątek osobno, można to zrobić w następujący sposób.
Rozważmy poniższy przykładowy kod Pythona
def get_fraction(value, idx): arr = [4,5,2,0] # lista liczb idx_value = arr[idx] # if idx is> arr length, IndexError will be raised value/idx_value # if idx_value == 0, ZeroDivisionError will be raised if __name__ =='__main__': # set 'value' and 'idx' value = 54 idx = 5 # call function in a try-excepts statement. try: result = get_fraction(value, idx) print("Fraction is ", result) exceptIndexError: print("idx of {} is out of range".format(idx)) except ZeroDivisionError: print("arr[{}] is 0. Hence, can't divide by zero".format(idx)) except Exception as ex: print(ex) print("Not sure what happened so not safe to continue, \ app will be interrupted") raise ex
Zauważyliśmy tutaj, że Exception został użyty w ostatniej instrukcji except. Dzieje się tak, ponieważ obiekt wyjątku Exception pasuje do każdego wyjątku. Z tego powodu powinien on być zawsze ostatni, ponieważ Python przestanie sprawdzać inne programy obsługi wyjątków, gdy jeden z nich zostanie dopasowany.
W powyższym kodzie, idx=5 stąd arr[idx] podniesie IndexError ponieważ idx jest większa niż długość listy arr
Ponadto, nie mając pewności, jaki wyjątek został zgłoszony przez aplikację, nigdy nie można bezpiecznie kontynuować jej wykonywania. Dlatego mamy typ Exception, aby wychwycić wszelkie nieprzewidziane wyjątki. Następnie informujemy użytkownika i przerywamy aplikację, zgłaszając ten sam wyjątek.
Oświadczenie Try Else
To jest funkcja opcjonalna obsługi wyjątków i umożliwia dodanie kodu, który ma zostać uruchomiony, gdy nie wystąpią żadne błędy. Jeśli wystąpi błąd, ten else-block nie zostanie uruchomiony.
Rozważ poniższy przykładowy kod Pythona, otwórz edytor i zapisz kod jako elseTry.py
def fraction_of_one(divisor): value = 1/divisor # jeśli dzielnik wynosi zero, zostanie zgłoszony błąd ZeroDivisionError return value if __name__ == '__main__': while True: try: # Pobierz dane wejściowe od użytkownika. # jeśli dane wejściowe nie są poprawnym argumentem dla int(), zostanie zgłoszony błąd ValueError divisor = int(input("Wprowadź dzielnik: ")) # wywołaj naszą funkcję, aby obliczyć ułamek value = fraction_of_one(divisor) except (ValueError,ZeroDivisionError): print("Wartość wejściowa nie może być zerem i powinna być prawidłową literałem dla int(). Proszę, spróbuj ponownie!") else: print("Wartość: ", wartość) break
Otrzymujemy dane wejściowe od użytkownika i używamy ich do podzielenia 1. Mamy tutaj dwa możliwe wyjątki: nieprawidłowe dane wejściowe użytkownika, które spowodują ValueError oraz zero(0) co spowoduje ZeroDivisionError Nasza instrukcja except obsługuje te błędy.
Teraz chcemy wydrukować wartość wartość Nasz else-block upewnia się, że jest on drukowany tylko wtedy, gdy nasz try-block wykona się bez błędu. Jest to ważne, ponieważ jeśli wystąpi błąd w naszym try-block, to wartość będzie niezdefiniowana, więc dostęp do niej spowoduje kolejny błąd.
Uruchom powyższy kod za pomocą Python elseTry.py
Powyższe dane wyjściowe pokazują, że dla pierwszego wejścia wpisaliśmy 0 Ponieważ nasz dzielnik otrzymał 0, 1/ dzielnik podniósł zeroDivisionError Nasze drugie dane wejściowe to k, które jest nieprawidłowe dla int (), stąd wyjątek ValueError jest podniesiony.
Ale nasze ostatnie dane wejściowe to 9, co jest prawidłowe i w rezultacie otrzymaliśmy wartość " wartość " wydrukowany jako 0.11111111111111111111
Wypróbuj wreszcie oświadczenie
Jest to również funkcja opcjonalna obsługi wyjątków i zawsze będzie działać bez względu na to, co dzieje się w programach obsługi wyjątków.
To znaczy:
- Czy wystąpił wyjątek
- Nawet jeśli "return" jest wywoływany w innych blokach.
- Nawet jeśli skrypt zostanie zamknięty w innych blokach
Tak więc, jeśli mamy kod, który chcemy uruchomić w każdej sytuacji, finally-block jest naszym facetem. Ten blok jest najczęściej używany do czyszczenia, takiego jak zamykanie plików.
Rozważmy poniższy przykładowy kod Pythona
def readFile(file_path): try: openFile = open(file_path,'r') # Otwórz plik tylko do odczytu print(openFile.readline()) # Odczytaj pierwszą linię zawartości pliku except FileNotFoundError as ex: print(ex) finally: print("Czyszczenie...") openFile.close() if __name__ == '__main__': filePath = './text.txt' readFile(filePath)
Ten kod próbuje otworzyć i odczytać plik text.txt w bieżącym katalogu. Jeśli plik istnieje, nasz program wypisze pierwszą linię pliku, a następnie nasz blok finally uruchomi się i zamknie plik.
Załóżmy, że mamy plik o nazwie text.txt w katalogu, w którym znajduje się ten plik programu i zawiera Hello. Jeśli uruchomimy program, otrzymamy dane wyjściowe
Ten przykład został wybrany celowo, ponieważ chciałem, abyśmy zajęli się małym problemem, który może wystąpić podczas zamykania plików w bloku finally.
Jeśli plik nie istnieje, zostanie zgłoszony wyjątek FileNotFoundError zostanie podniesiona, a zmienna openFile nie zostanie zdefiniowany i nie będzie obiektem pliku. Dlatego próba zamknięcia go w bloku finally spowoduje zgłoszenie wyjątku UnboundLocalError która jest podklasą NameError .
Zasadniczo mówi to, że próbujemy odwołać się do zmiennej openFile przed jego przypisaniem.
Małą sztuczką jest użycie obsługi wyjątków wewnątrz bloku finally.
def readFile(file_path): try: openFile = open(file_path,'r') # Otwórz plik tylko do odczytu print(openFile.readline()) # Odczytaj pierwszą linię zawartości pliku except FileNotFoundError as ex: print(ex) finally: try: print("Czyszczenie...") openFile.close() except: # wyłapuje wszystkie wyjątki pass # Ignorujemy ten błąd, ponieważ nas nie obchodzi. if __name__ == '__main__': filePath = './text.txt' readFile(filePath)
Jeśli nasz try-block zgłosi błąd FileNotFoundError, otrzymamy następujące dane wyjściowe
Podnieś wyjątek
Jedną z dobrych wiadomości na temat wyjątków Pythona jest to, że możemy je celowo zgłaszać. Wyjątki są zgłaszane za pomocą funkcji podnieść oświadczenie .
Instrukcja raise ma następującą składnię:
raise [ExceptionName[(*args: Object)]]
Otwórz terminal i podnieś dowolny obiekt wyjątku z wbudowanej listy wyjątków Pythona. Na przykład, jeśli podniesiemy ZeroDivisionError:
>>> raise ZeroDivisionError("Nie można dzielić przez zero")
Otrzymamy informację zwrotną:
Dlaczego więc ważne jest podnoszenie wyjątków?
- Podczas pracy z niestandardowymi wyjątkami.
- Podczas kontroli zdrowia psychicznego.
Niestandardowe klasy wyjątków
Niestandardowy wyjątek to taki, który tworzysz w celu obsługi błędów specyficznych dla twoich potrzeb. Sztuczka polega na tym, że definiujemy klasę, która wywodzi się z obiektu Wyjątek Następnie używamy instrukcji raise, aby podnieść naszą klasę wyjątków.
Załóżmy, że chcemy sprawdzić dane wprowadzane przez użytkownika i upewnić się, że wartość wejściowa nie jest ujemna (kontrola poprawności). Oczywiście moglibyśmy podnieść wyjątek Pythona ValueError, ale chcielibyśmy dostosować błąd, nadając mu konkretną i zrozumiałą nazwę, taką jak InputIsNegativeError Ale ten wyjątek nie jest wbudowanym wyjątkiem Pythona.
Najpierw więc tworzymy naszą klasę bazową, która będzie pochodną od Exception.
class CustomError(Exception): "Wyjątek klasy bazowej dla wszystkich wyjątków tego modułu" pass
Następnie tworzymy naszą klasę wyjątku, która będzie dziedziczyć po klasie bazowej i będzie obsługiwać nasz konkretny błąd.
class InputIsNegativeError(CustomError): """Zgłaszany, gdy użytkownik wprowadzi wartość ujemną"" pass
Przetestujmy to
try: value = int(input()) if value <0: raise InputIsNegativeError # raise exception if value is negative except InputIsNegativeError: # catch and handle exception print("Wartość wejściowa nie powinna być ujemna")
Powyższy kod żąda danych wejściowych użytkownika i sprawdza, czy są one ujemne. Jeśli tak, zgłasza nasz niestandardowy wyjątek InputIsNegativeError, który jest później przechwytywany w instrukcji except.
Poniżej znajduje się kompletny kod:
class CustomError(Exception): "Wyjątek klasy bazowej dla wszystkich wyjątków tego modułu" pass class InputIsNegativeError(CustomError): """Podnoszony, gdy użytkownik wprowadzi wartość ujemną"" pass if __name__ == '__main__': try: value = int(input("Wprowadź liczbę: ")) if value <0: raise InputIsNegativeError # Podnieś wyjątek, jeśli wartość jest ujemna except InputIsNegativeError: # złap i obsłuż wyjątekprint("Wartość wejściowa nie powinna być ujemna")
Jeśli wartość wejściowa jest liczbą ujemną, taką jak -1, wówczas otrzymamy wartość wyjściową:
Więcej szczegółów na temat niestandardowych wyjątków Pythona można znaleźć w dokumentacji Pythona.
Często zadawane pytania
P #1) Jak Python radzi sobie z wyjątkami?
Odpowiedź: Python obsługuje wyjątki przy użyciu funkcji instrukcja try-except Kod, który może zgłosić wyjątek, jest umieszczany i wykonywany w sekcji próba bloku podczas gdy z wyjątkiem bloku zawiera kod, który będzie obsługiwał wyjątki, jeśli takie wystąpią.
P #2) Czym jest podnoszenie wyjątku w Pythonie?
Odpowiedź: Za każdym razem, gdy interpreter Pythona napotka nieprawidłowy kod, zgłasza wyjątek, który jest sposobem Pythona na poinformowanie nas, że wydarzyło się coś nieoczekiwanego. Możemy również celowo zgłaszać wyjątki za pomocą funkcji podnieść oświadczenie .
P #3) Jak Python radzi sobie z wieloma wyjątkami?
Odpowiedź: Python obsługuje wiele wyjątków za pomocą pojedynczego bloku except lub wielu bloków except.
W przypadku pojedynczego bloku wyjątki są przekazywane jako krotka: z wyjątkiem (Exception1, Exception2,...,ExceptionN) i Python sprawdza dopasowanie od prawej do lewej. W tym przypadku ta sama akcja jest podejmowana dla każdego wyjątku.
Innym sposobem na wychwycenie wszystkich wyjątków jest pominięcie nazwy wyjątku po słowie kluczowym except.
except: # obsługuje wszystkie wyjątki tutaj
Drugim sposobem jest użycie bloku except dla każdego wyjątku:
except Exception1: # kod do obsługi Exception1 przechodzi tutaj except Exception2: # kod do obsługi Exception2 przechodzi tutaj except ExceptionN: # kod do obsługi ExceptionN przechodzi tutaj
W ten sposób można podjąć oddzielne działania dla każdego wyjątku.
P #4) Dlaczego obsługa wyjątków jest ważna w Pythonie?
Odpowiedź: Zaletą obsługi wyjątków w Pythonie jest to, że możemy tworzyć solidne, czyste i wolne od błędów aplikacje. Nie chcemy, aby nasz kod produkcyjny zawiesił się z powodu pewnych błędów, więc obsługujemy błędy i utrzymujemy naszą aplikację w ruchu.
P #5) Jak zignorować wyjątek w Pythonie?
Odpowiedź: Aby zignorować wyjątek w Pythonie, należy użyć funkcji przepustka Powiedzmy, że chcemy zignorować wyjątek ValueError. Zrobimy to w ten sposób:
except ValueError: pass
Jeśli nie wiesz, co robisz, złą praktyką jest ignorowanie wyjątków. Przynajmniej poinformuj użytkownika o wszystkich potencjalnych błędach.
Wnioski
W tym samouczku omówiliśmy: Wyjątki Pythona, Traceback; jak obsługiwać wyjątki za pomocą Spróbuj / Z wyjątkiem / Else / Wreszcie bloki, jak Podniesienie Wyjątki i wreszcie, jak tworzyć własne niestandardowe wyjątki.
Dzięki za przeczytanie!