PPy3/TematyDodatkowe: Różnice pomiędzy wersjami
Linia 46: | Linia 46: | ||
Tutaj już jaśniej być nie może; interpreter nie tylko wskazał nam dokładne miejsce wystąpienia błędu, ale nawet dokładnie opisał, jak go naprawić. | Tutaj już jaśniej być nie może; interpreter nie tylko wskazał nam dokładne miejsce wystąpienia błędu, ale nawet dokładnie opisał, jak go naprawić. | ||
+ | |||
+ | Oczywiście nie zawsze interpreter będzie w stanie wskazać nam błąd aż tak precyzyjnie. Jako przykład weźmy następujący plik: | ||
+ | |||
+ | <source lang=python> | ||
+ | x, y, z = 3, 4, 5 | ||
+ | print(max(x, y, z) | ||
+ | print(X * y * z) | ||
+ | </source> | ||
+ | |||
+ | i wynik jego uruchomienia: | ||
+ | |||
+ | <source lang=bash> | ||
+ | $ python3 błąd.py | ||
+ | File "błąd.py", line 3 | ||
+ | print(X * y * z) | ||
+ | ^ | ||
+ | SyntaxError: invalid syntax | ||
+ | </source> | ||
+ | |||
+ | Dlaczego został wytknięty błąd składniowy w linijce 3? Przecież to w linijce 2 zapomnieliśmy zamknąć jeden z nawiasów. | ||
+ | |||
+ | Otóż jeżeli z końcem linii Python stwierdza, że nie wszystkie dotąd otwarte nawiasy zostały zamknięte, to traktuje to jako oznaczające, że kolejną linijkę należy potraktować jako ciąg dalszy bieżącej. I w tym przypadku dopiero napotykając w kolejnej linijce nazwę <tt>print</tt> — a nie np. przecinek, albo nawias zamykający — stwierdza, że coś musi być nie tak. Miejsce wykrycia błędu niestety nie zawsze się będzie pokrywało z miejscem jego faktycznego wystąpienia. | ||
+ | |||
+ | Po poprawce, czyli zamknięciu nawiasu na linii 2, próbujemy jeszcze raz — z wynikiem | ||
+ | |||
+ | <source lang=bash> | ||
+ | python3 błąd.py | ||
+ | 5 | ||
+ | Traceback (most recent call last): | ||
+ | File "błąd.py", line 3, in <module> | ||
+ | print(X * y * z) | ||
+ | NameError: name 'X' is not defined | ||
+ | </source> | ||
+ | |||
+ | I tym razem chyba jest wszystko jasne: pojawiła się nazwa <tt>X</tt>, z którą wcześniej nie związano żadnej wartości. Po prostu przez pomyłkę napisaliśmy X wielką literą zamiast małą. | ||
+ | |||
+ | Te przykłady pokazują, że przy wykorzystaniu treści wypisywanych komunikatów proces usunięcia z programu błędów składniowych i formalnych może być dość szybki i bezbolesny. | ||
== Klasy własnej produkcji == | == Klasy własnej produkcji == |
Wersja z 12:57, 27 mar 2018
Spis treści
Tematy dodatkowe
Błędy i wyjątki
Każdy programista popełnia błędy — jest to nieunikniona część tej działalności.
- Są błędy, które można nazwać banalnymi: literówka w nazwie lub słowie kluczowym, zapomniany dwukropek, niedomknięte nawiasy, itp.
- Są bardziej podstępne błędy logiczne: gdy algorytm, którego zapisem ma być tworzony kod, po prostu nie robi dokładnie tego, co nam się wydaje.
- I w końcu są sytuacje wyjątkowe: gdy w toku pracy programu zachodzą nieoczekiwane okoliczności — użytkownik podał błędną nazwę pliku z danymi, zawartość tego pliku nie jest zgodna z oczekiwaniami programu, połączenie sieciowe ulega przerwaniu w trakcie pobierania lub przesyłania danych, itp.
Wszystkie te sytuacje nazywa się wyjątkami, i tym samym słowem określa się mechanizm, jakiego wiele współczesnych języków programowania (w tym Python) dostarcza programiście, aby mu pomóc określić działania jakie program miałby podjąć w sytuacjach wyjątkowych. Wyjątkowość takich sytuacji generalnie polega na tym, że w przypadku ich wystąpienia program po prostu nie może kontynuować przewidzianego toku działania:
- błąd w składni programu oznacza, że kod nie daje się zinterpretować w sposób jednoznaczny; najlepsze co można zrobić, to w momencie wykrycia błędu przerwać działanie i spróbować dostarczyć programiście (w formie komunikatu) informację ułatwiającą określenie i naprawienie błędu;
- błędne działanie algorytmu można np. spróbować wykrywać za pomocą tzw. asercji (polecenie assert) badających, czy pewne warunki, jakie powinny być spełnione przez dane przetwarzane w programie są istotnie spełnione;
- wyjątki powstałe na skutek okoliczności zachodzących w trakcie działania programu, uniemożliwiających jego normalną kontynuację, można spróbować przewidzieć i przygotować program do odpowiedniego zareagowania, czyli obsługi wyjątku. Na przykład, można spróbować ponowić jeszcze raz (lub kilka razy) próbę łączności sieciowej, i poddać się dopiero po określonej liczbie niepowodzeń; natomiast w sytuacji błędu wynikającego z podania przez użytkownika programu niewłaściwych argumentów uruchomienia, warto postarać się o przekazanie użytkownikowi komunikatu informującego go w sposób dla niego zrozumiały, o właściwym sposobie uruchamiania programu.
Błędy składniowe i podobne
Jak wspomniano powyżej, w przypadku napotkania błędu składniowego w kodzie programu interpreter natychmiast przerwie wykonywanie programu i wypisze komunikat. Komunikaty te warto czytać uważnie — w większości przypadków znajduje się w nich cała informacja konieczna dla naprawienia błędu. Przykład: usiłujemy uruchomić program błąd.py, którego treść to
x = (2 + 3) 4
print x
Wynik pierwszej próby to:
$ python3 błąd.py
File "błąd.py", line 1
x = (2 + 3) 4
^
SyntaxError: invalid syntax
Z komunikatu całkiem jasno wynika, że napotkany został błąd składni (SyntaxError), że wykryto ten błąd w linijce 1, a nawet dokładnie — że miejscem, w którym interpreter stwierdził, że ma do czynienia z nieprawidłowy kodem, było wystąpienie cyfry 4 po zamykającym nawiasie. Po prostu zapomnieliśmy, że — inaczej niż w powszechnie stosowanej notacji matematycznej — w Pythonie aby uzyskać mnożenie, konieczne jest napisanie jawnie znaku operatora (gwiazdki).
Po naprawieniu tej pomyłki próbujemy jeszcze raz, i wynik to:
$ python3 błąd.py
File "błąd.py", line 2
print x
^
SyntaxError: Missing parentheses in call to 'print'. Did you mean print(x)?
Tutaj już jaśniej być nie może; interpreter nie tylko wskazał nam dokładne miejsce wystąpienia błędu, ale nawet dokładnie opisał, jak go naprawić.
Oczywiście nie zawsze interpreter będzie w stanie wskazać nam błąd aż tak precyzyjnie. Jako przykład weźmy następujący plik:
x, y, z = 3, 4, 5
print(max(x, y, z)
print(X * y * z)
i wynik jego uruchomienia:
$ python3 błąd.py
File "błąd.py", line 3
print(X * y * z)
^
SyntaxError: invalid syntax
Dlaczego został wytknięty błąd składniowy w linijce 3? Przecież to w linijce 2 zapomnieliśmy zamknąć jeden z nawiasów.
Otóż jeżeli z końcem linii Python stwierdza, że nie wszystkie dotąd otwarte nawiasy zostały zamknięte, to traktuje to jako oznaczające, że kolejną linijkę należy potraktować jako ciąg dalszy bieżącej. I w tym przypadku dopiero napotykając w kolejnej linijce nazwę print — a nie np. przecinek, albo nawias zamykający — stwierdza, że coś musi być nie tak. Miejsce wykrycia błędu niestety nie zawsze się będzie pokrywało z miejscem jego faktycznego wystąpienia.
Po poprawce, czyli zamknięciu nawiasu na linii 2, próbujemy jeszcze raz — z wynikiem
python3 błąd.py
5
Traceback (most recent call last):
File "błąd.py", line 3, in <module>
print(X * y * z)
NameError: name 'X' is not defined
I tym razem chyba jest wszystko jasne: pojawiła się nazwa X, z którą wcześniej nie związano żadnej wartości. Po prostu przez pomyłkę napisaliśmy X wielką literą zamiast małą.
Te przykłady pokazują, że przy wykorzystaniu treści wypisywanych komunikatów proces usunięcia z programu błędów składniowych i formalnych może być dość szybki i bezbolesny.