|
Rozdział 7: Błędy i wyjątki 1: Błędy składni
- 2: Wyjątki - 3: Obsługa wyjątków
- 4: Zgłaszanie wyjątków 5: Wyjątki definiowane przez użytkownika
- 6: Jak posprzątać po bałaganiarzu?
Lekcja 3: Obsługa wyjątków
Możliwe jest napisanie programu, który obsługuje wybrane wyjątki. W poniższym przykładzie
użytkownik podaje dane na wejściu aż do momentu, kiedy zostanie wprowadzona
poprawna liczba całkowita. Użytkownik może przerwać pracę (poprzez naciśnięcie Control-C lub
dowolny sposobem, jaki jest możliwy poprzez klawiaturę w danym systemie operacyjnym). Przerwanie
użytkownika sygnalizowane jest poprzez zgłoszenie wyjątku KeyboardInterrupt.
>>> while 1:
... try:
... x = int(raw_input("Prosze wprowadzic liczbe: "))
... break
... except ValueError:
... print "Uch! to nie jest poprawna liczba! Sprobuj jeszcze raz..."
...
Prosze wprowadzic liczbe:
Jak działa instrukcja try:
- Na początku wykonywana jest klauzula try (czyli instrukcje pomiędzy try a except).
- Jeżeli nie pojawi się żaden wyjątek klauzula except jest pomijana. Wykonanie instrukcji try
uważa się za zakończone.
Jeżeli podczas wykonywania klauzuli try pojawi się wyjątek, reszta niewykonanych instrukcji
jest pomijana. Następnie, w zależności od tego, czy jego typ pasuje do typów wyjątków
wymienionych w części except, wykonywany jest kod następujący w tym bloku, a potem interpreter
przechodzi do wykonywania instrukcji umieszczonych po całym bloku try...except.
-
W przypadku pojawienia się wyjątku, który nie zostanie dopasowany do żadnego z wyjątków
wymienionych w klauzuli except, zostaje on przekazany do do następnych, zewnętrznych instrukcji
try. Jeżeli również tam nie zostanie znaleziony odpowiadający mu blok except, wyjątek ten nie
zostanie wyłapany, stanie nieobsłużonym wyjątkiem, a wykonywanie programu zostanie wstrzymane
wraz z pojawieniem się komunikatu podobnego do pokazanego powyżej.
Aby umożliwić obsługę wielu wyjątków, instrukcja try może posiadać więcej niż jedną klauzulę
except. W takim przypadku, kod dla co najwyżej jednego wyjątku zostanie wykonany. Kody obsługi
wyjątków wykonywane są tylko dla wyjątków, które zostały zgłoszone w odpowiadającej im części
try, a nie w innych, sąsiednich częściach except. Klauzula except może zawierać nazwy wielu
wyjątków, podanych w formie listy otoczonej nawiasami okrągłymi (czyli w formie krotki):
... except (RuntimeError, TypeError, NameError):
... pass
W ostatniej podanej klauzuli except można pominąć nazwę lub nazwy wyjątków w celu obsłużenia
dowolnego wyjątku. Należy posługiwać się tą konstrukcją bardzo ostrożnie, ponieważ jest to
sposób do łatwego zamaskowania prawdziwego wystąpienia błędu w programie! Można jej również
użyć do wydrukowania komunikatu o błędzie i ponownie zgłosić wyłapany wyjątek (umożliwiając w
ten sposób funkcji wywołującej wyłapanie zgłoszonego wyjątku):
import string, sys
try:
f = open('mojplik.txt')
s = f.readline()
i = int(string.strip(s))
except IOError, (errno, strerror):
print "Blad I/O (%s): %s" % (errno, strerror)
except ValueError:
print "Nie moge przeksztalcic danej w liczbe calkowita."
except:
print "Nieobslugiwany blad:", sys.exc_info()[0]
raise
Instrukcja try ... except wyposażona jest w opcjonalną klauzulę else, która musi pojawić się za
wszystkimi podanymi blokami except. Można po niej umieścić kod, który zostanie wykonany, jeżeli
nie zostanie zgłoszony wyjątek:
for arg in sys.argv[1:]:
try:
f = open(arg, 'r')
except IOError:
print 'nie moge otworzyc pliku', arg
else:
print arg, 'ma', len(f.readlines()), 'linie/linii'
f.close()
Wyjątek może pojawić się z przypisaną sobie wartością, która nazywana jest argumentem wyjątku.
Obecność tej wartości i jej typ zależy od rodzaju wyjątku. Jeżeli chce się poznać tę wartość,
należy podać nazwę zmiennej (lub listę zamiennych) za nazwą typu wyjątku w klauzuli except:
>>> try:
... szynka()
... except NameError, x:
... print 'nazwa', x, 'nie została zdefiniowana'
...
nazwa szynka nie została zdefiniowana
Argument ten (jeśli istnieje) pokazywany jest w ostatniej części («detail» ) komunikatu o
niewyłapanym wyjątku.
Kody obsługujące wyjątek uruchamiane są nie tylko po zgłoszeniu wyjątku w ich klauzuli try,
ale także w przypadku, gdy pojawią się one w instrukcjach try umieszczonych w wywoływanych
funkcjach (nawet pośrednio):
>>> def to_sie_nie_uda():
... x = 1/0
...
>>> try:
... this_fails()
... except ZeroDivisionError, detale:
... print 'Obsługa błędu wykonania programu:', detale
...
Obsługa błędu wykonania programu: integer division or modulo
|
|