Wyjątki

Stronę tą wyświetlono już: 260 razy

Kiedy coś pójdzie nie tak...

No właśnie, gdy coś pójdzie nie tak i w kodzie programu znajdzie się błąd chciałoby się, aby program wyświetlił naturę tego błędu. Obsługą błędów zajmują się wyjątki (exception), zanim jednak je omówię pokażę jak działają już wbudowane wyjątki:

Listing 1
  1. x = 1 / 0

Powyższy błąd wywoła obsługę wyjątku związanego z dzieleniem przez zero, oto co wyświetli się w konsoli po wykonaniu tego działania:

-------------------------------------------------------------------
ZeroDivisionError                         Traceback (most recent call last)
 in ()
----> 1 x = 1/0

ZeroDivisionError: division by zero

W konsoli ładnie i przejrzyście wyświetlone zostały informacje co poszło nie tak i gdzie poszło nie tak. W tym przypadku wywołany został wyjątek ZeroDivisionError, czyli dzielenie przez zero.

Kolejny przykład działania wbudowanych wyjątków:

Listing 2
  1. y = 10
  2. x = 5 * (1 - y))

Powyższy kod wywoła następujący wyjątek:

In [5]: x = 5 * (1 - y))
  File "", line 1
    x = 5 * (1 - y))
                   ^
SyntaxError: invalid syntax

Tym razem wyjątek to SyntaxError (błąd składni).

Jak widać wyjątki są dość ważne, ponieważ wskazują jaki błąd został popełniony, i gdzie został popełniony co ułatwia eliminację błędu.

Przechwytywanie wyjątków

Wyjątki są przechwytywane za pomocą try, except w następujący przykładowy sposób:

Listing 3
  1. while True:
  2. try:
  3. k = int(input("Podaj jakąś wartość liczbową: "))
  4. break
  5. except ValueError:
  6. print("To raczej liczba nie jest. Spróbuj ponownie!")

Przykład działania tego kodu:

Podaj jakąś liczbę: s
To raczej liczba nie jest. Spróbuj ponownie!
Podaj jakąś liczbę: 10

Oczywiście możliwe jest obsłużenie kilku różnych wyjątków, np w następujący sposób:

Listing 4
  1. try:
  2. exp = eval(input("Podaj wyrażenie do obliczenia: "))
  3. except ZeroDivisionError as e:
  4. print('Dzielisz przez zero ({0})'.format(e))
  5. except NameError as e:
  6. print('Nieznana zmienna ({0})'.format(e))
  7. except TypeError as e:
  8. print("Błąd typu danych lub deklaracji zmiennej ({0})".format(e), calcText)
  9. except:
  10. print("Błąd składni")
  11. else:
  12. print(exp)

W powyższym kodzie wykorzystana została funkcja eval, która jako argument przyjmuje tekst. Tekst ten jest interpretowany jak kod Pythona. Żeby być szczególnie dokładnym chodzi o jednoliniowy kod. Wewnątrz tekstu może znajdować się wszystko co prowadzi do konkluzji, że użytkownik może wpisać jakąś głupotę. Warto więc obsłużyć w odpowiedni sposób wyjątki, co też i powyższy kod czyni.

Oto przykład działania powyższego kodu:

Podaj wyrażenie do obliczenia: 2 * 3 / 0
Dzielisz przez zero (division by zero)

Szczegółowa lista wyjątków, jakie można przechwycić została opisana na stronie docs.python.org. Poniżej zamieszczam listę tychże wyjątków:

  • BaseException;
  • Exception;
  • StandardException;
  • ArithmeticalError - kombinacja wyjątków OverflowError, ZeroDivisionError i FloatingPointError;
  • BufferError;
  • LookupError;
  • EnviromentError;
  • AssertionError;
  • AtteributeError;
  • EOFError;
  • FloatingPointError;
  • GeneratorExit;
  • IOError;
  • ImportError;
  • IndexError;
  • KeyError;
  • KeyboardInterrupt;
  • MemoryError;
  • NameError;
  • NotImplementedError;
  • OSError;
  • OverflowError;
  • ReferenceError;
  • RuntimeError;
  • StopIteration;
  • SyntaxError;
  • IndentationError;
  • TabError;
  • SystemError;
  • SystemExit;
  • TypeError;
  • UnboundLocalError;
  • UnicodeError;
  • UnicodeEncodeError;
  • UnicodeDecodeError;
  • UnicodeTranslateError;
  • ValueError;
  • VMSError;
  • WindowsError;
  • ZeroDivisionError;
  • Warning;
  • UserWarning;
  • DepracationWarning;
  • SystaxWarning;
  • RuntimeWarning;
  • FutureWarning;
  • ImportWarning;
  • UnicodeWarning

Tworzenie własnych wyjątków:

Istnieje też możliwość tworzenia swoich własnych wyjątków, choć zalecane jest wykorzystywanie wyjątków wymienionych na powyższej liście. Oto przykład kodu wykorzystującego własnoręcznie utworzony wyjątek:

Listing 5
  1. class NegativeValue(Exception):
  2. pass
  3. def silnia(n):
  4. if n < 0:
  5. raise NegativeValue()
  6. s = 1
  7. if n < 2:
  8. return 1
  9. for i in range(2, n + 1):
  10. s *= i
  11. return s
  12. try:
  13. print(silnia(int(input("Podaj liczbę, której silnię chcesz obliczyć: "))))
  14. except NegativeValue:
  15. print("Nie możn aobliczyć silni z ujemnej liczby")
  16. except:
  17. print("Wyjątek")

W powyższym przykładzie klasa NegativeValue jest klasą obsługi własnego błędu. Taka klasa musi dziedziczyć po klasie Exception. Nasz wyjątek zostanie wywołany wewnątrz funkcji Silnia za pomocą słowa kluczowego raise jako odpowiedź na podanie jako argumentu tej funkcji liczby ujemnej.

Komentarze