<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="pl">
	<id>http://brain.fuw.edu.pl/edu/index.php?action=history&amp;feed=atom&amp;title=TI%2FWyj%C4%85tki</id>
	<title>TI/Wyjątki - Historia wersji</title>
	<link rel="self" type="application/atom+xml" href="http://brain.fuw.edu.pl/edu/index.php?action=history&amp;feed=atom&amp;title=TI%2FWyj%C4%85tki"/>
	<link rel="alternate" type="text/html" href="http://brain.fuw.edu.pl/edu/index.php?title=TI/Wyj%C4%85tki&amp;action=history"/>
	<updated>2026-04-26T18:18:32Z</updated>
	<subtitle>Historia wersji tej strony wiki</subtitle>
	<generator>MediaWiki 1.34.1</generator>
	<entry>
		<id>http://brain.fuw.edu.pl/edu/index.php?title=TI/Wyj%C4%85tki&amp;diff=1663&amp;oldid=prev</id>
		<title>Jarekz o 20:57, 22 maj 2015</title>
		<link rel="alternate" type="text/html" href="http://brain.fuw.edu.pl/edu/index.php?title=TI/Wyj%C4%85tki&amp;diff=1663&amp;oldid=prev"/>
		<updated>2015-05-22T20:57:15Z</updated>

		<summary type="html">&lt;p&gt;&lt;/p&gt;
&lt;table class=&quot;diff diff-contentalign-left&quot; data-mw=&quot;interface&quot;&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;pl&quot;&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #222; text-align: center;&quot;&gt;← poprzednia wersja&lt;/td&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #222; text-align: center;&quot;&gt;Wersja z 20:57, 22 maj 2015&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot; id=&quot;mw-diff-left-l1&quot; &gt;Linia 1:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Linia 1:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt;−&lt;/td&gt;&lt;td style=&quot;color: #222; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;&lt;/del&gt;&lt;/div&gt;&lt;/td&gt;&lt;td colspan=&quot;2&quot;&gt; &lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #222; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;== Informowanie o błędach ==&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #222; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;== Informowanie o błędach ==&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #222; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;Czasami w trakcie wykonywania operacji przez program występuje sytuacja, która uniemożliwia jej wykonanie. Typowe sytuacje wymagające specjalnych reakcji programu to:&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #222; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;Czasami w trakcie wykonywania operacji przez program występuje sytuacja, która uniemożliwia jej wykonanie. Typowe sytuacje wymagające specjalnych reakcji programu to:&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;</summary>
		<author><name>Jarekz</name></author>
		
	</entry>
	<entry>
		<id>http://brain.fuw.edu.pl/edu/index.php?title=TI/Wyj%C4%85tki&amp;diff=1659&amp;oldid=prev</id>
		<title>Jarekz: Utworzono nową stronę &quot; == Informowanie o błędach == Czasami w trakcie wykonywania operacji przez program występuje sytuacja, która uniemożliwia jej wykonanie. Typowe sytuacje wymagające...&quot;</title>
		<link rel="alternate" type="text/html" href="http://brain.fuw.edu.pl/edu/index.php?title=TI/Wyj%C4%85tki&amp;diff=1659&amp;oldid=prev"/>
		<updated>2015-05-22T20:53:27Z</updated>

		<summary type="html">&lt;p&gt;Utworzono nową stronę &amp;quot; == Informowanie o błędach == Czasami w trakcie wykonywania operacji przez program występuje sytuacja, która uniemożliwia jej wykonanie. Typowe sytuacje wymagające...&amp;quot;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Nowa strona&lt;/b&gt;&lt;/p&gt;&lt;div&gt;&lt;br /&gt;
== Informowanie o błędach ==&lt;br /&gt;
Czasami w trakcie wykonywania operacji przez program występuje sytuacja, która uniemożliwia jej wykonanie. Typowe sytuacje wymagające specjalnych reakcji programu to:&lt;br /&gt;
# błąd w korzystaniu z zewnętrznych zasobów np.:&lt;br /&gt;
#* program miał za zadanie otworzyć plik o określonej nazwie, a okazało się, że takiego pliku nie ma&lt;br /&gt;
#* program miał pobrać stronę www ze zdalnego serwera, a nie udaje się nawiązać połączenia&lt;br /&gt;
# niemożność poprawnego wykonania&lt;br /&gt;
#* program miał za zadanie znaleźć długość ósmej linijki w pliku, a plik ma tylko siedem linijek&lt;br /&gt;
#* program miał obliczyć pierwiastek liczby podanej przez użytkownika, a podana liczba jest ujemna (i program nie jest świadomy istnienia liczb zespolonych)&lt;br /&gt;
# pogwałcenie wewnętrznej spójności programu: w miarę jak program się rozrasta rośnie prawdopodobieństwo, że wywołamy funkcję w sposób niezgodny z jej wymaganiami&lt;br /&gt;
#* np. funkcja znajdująca liczbę w tablicy oczekuje tablicy posortowanej, a wywołamy ją z tablicą nieposortowaną&lt;br /&gt;
#* np. zmienna opisująca promień koła ma wartość ujemną&lt;br /&gt;
&lt;br /&gt;
Problem obsługi sytuacji wyjątkowych jest dodatkowo skomplikowany przez fakt, że często sytuacja wymagająca specjalnego obsłużenia występuje w funkcji, która została wywołana przez inną funkcję, która została wywołana przez inną funkcję,... Niemniej, właściwym miejscem na reakcję, często nie jest miejsce stwierdzenia błędu, gdzieś głęboko w wywołaniu funkcji wykonującej jedno specjalizowane zadanie, a wręcz przeciwnie, bardzo płytko, w miejscu sterowania całym wykonaniem programu.&lt;br /&gt;
&lt;br /&gt;
Jako przykład rozważmy podany wcześniej błąd otwarcia pliku. Jeśli taki błąd zostanie napotkany przez program, którego zadaniem było odczytać z dysku i wyświetlić jedno zdjęcie, to właściwą reakcją będzie wypisanie informacji o błędzie i zakończenie działania programu. Jeśli taki błąd wystąpi w działaniu przeglądarki ściągającej pliki ze zdalnego serwera i przechowującej tymczasowo pliki na dysku, to właściwą reakcją będzie ponowne ściągnięcie zdjęcia ze zdalnego serwera, bez informowania użytkownika lub przerywania pracy.&lt;br /&gt;
&lt;br /&gt;
Potrzebny jest zatem mechanizm przekazywania informacji o błędzie wzdłuż  łańcucha wywołań funkcji.&lt;br /&gt;
Jednym z takich mechanizmów są tzw. ''wyjątki''.&lt;br /&gt;
&lt;br /&gt;
== Jak działają wyjątki w Pythonie — rzucanie ==&lt;br /&gt;
Zasygnalizowanie w programie sytuacji nietypowej, która nie powinna się normalnie wydarzyć (czyli sytuacji wyjątkowej) nazywa się „rzuceniem” lub „podniesieniem” wyjątku. Informacje precyzujące zaistniałą sytuację są zapamiętywane. W tym celu zostaje stworzony obiekt nazywany wyjątkiem (''exception''). Dzieje się to wszystko z wykorzystaniem instrukcji &amp;lt;tt&amp;gt;raise&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&amp;lt;source lang= python&amp;gt;&lt;br /&gt;
  raise &amp;lt;typ-wyjątku&amp;gt;(argumenty precyzujące sytuację)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Na przykład żeby zasygnalizować, że funkcja została wywołana z nieodpowiednim argumentem (np. liczbą ujemną gdy oczekiwaliśmy dodatniej), można rzucić wyjątek typu &amp;lt;tt&amp;gt;ValueError&amp;lt;/tt&amp;gt; (zgodnie z konwencją używany w takiej sytuacji).&lt;br /&gt;
&amp;lt;source lang= python&amp;gt;&lt;br /&gt;
  raise ValueError('liczba ujemna')&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wyjątek może też zostać rzucony nie przez program, a przez samego Pythona (interpreter programu). Np. gdy program spróbuje wykonać niedozwolone dzielenie przez 0, zostaje automatycznie rzucony wyjątek typu &amp;lt;tt&amp;gt;ZeroDivisionError&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Jeśli w czasie wykonywania pewnej funkcji zostanie rzucony wyjątek (niezależnie czy ''explicite'', czy automatycznie), to wykonywanie tej funkcji zostanie przerwane i program powróci do miejsca, z którego ta funkcja została wywołana tzn. do funkcji o jeden poziom wyżej. Wykonywanie kolejnych funkcji jest przerywane, aż dojdziemy do najwyższego poziomu. Tam, jako domyślna reakcja na błąd, zostaje wypisana informacja o wystąpieniu wyjątku (jego typ, miejsce wystąpienia, jak też dodatkowe informacje) i program kończy działanie.&lt;br /&gt;
&lt;br /&gt;
== Obsługa wyjątków w Pythonie — chwytanie ==&lt;br /&gt;
&lt;br /&gt;
Domyślna reakcja Pythona na błąd nie zawsze jest pożądana. Jak wynika z przykładu z przeglądarką internetową, czasami właściwą reakcją nie jest przerwanie działania, ale podjęcie działań zaradczych (załadowanie zdjęcia z oryginalnego serwera) i kontynuowanie wykonywania programu. Mechanizm kaskadowego przerywania funkcji (i w konsekwencji całego programu) w momencie wystąpienia wyjątku może być kontrolowany. Służy do tego konstrukcja &amp;lt;tt&amp;gt;try...except&amp;lt;/tt&amp;gt;. W bloku programu pomiędzy &amp;lt;tt&amp;gt;try:&amp;lt;/tt&amp;gt; a &amp;lt;tt&amp;gt;except&amp;lt;/tt&amp;gt; wpisujemy fragment kodu, który może rzucić wyjątek. W bloku programu występującym po &amp;lt;tt&amp;gt;except:&amp;lt;/tt&amp;gt; opisujemy co należy zrobić jeśli pojawi się konkretny typ wyjątku. Podstawowa składnia jest następująca:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang= python&amp;gt;&lt;br /&gt;
  try:&lt;br /&gt;
      &amp;lt;operacje-mogące-rzucić-wyjątek&amp;gt;&lt;br /&gt;
  except &amp;lt;typ-wyjątku&amp;gt; as &amp;lt;nazwa-zmiennej&amp;gt;:&lt;br /&gt;
      &amp;lt;operacje-zaradcze&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
W przykładzie z przeglądarką internetową:&lt;br /&gt;
&amp;lt;source lang= python&amp;gt;&lt;br /&gt;
def wyswietl_obrazek(nazwa):&lt;br /&gt;
  try:&lt;br /&gt;
    obrazek = wczytaj_z_przechowalni(nazwa)&lt;br /&gt;
  except BladOdczytuZPrzechowalni as opis:&lt;br /&gt;
    zapisz_do_dziennika('nie udało się odczytać z przechowalni:' + nazwa, opis)&lt;br /&gt;
    obrazek = wczytaj_z_serwera(nazwa)&lt;br /&gt;
  wyswietl(obrazek)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Jeśli funkcja &amp;lt;tt&amp;gt;wczytaj_z_przechowalni()&amp;lt;/tt&amp;gt; rzuci wyjątek typu &amp;lt;tt&amp;gt;BladOdczytuZPrzechowalni&amp;lt;/tt&amp;gt;, jesteśmy przygotowani na jego obsługę i wywołujemy &amp;lt;tt&amp;gt;wczytaj_z_serwera()&amp;lt;/tt&amp;gt;. Jeśli operacja &amp;lt;tt&amp;gt;wczytaj_z_przechowalni()&amp;lt;/tt&amp;gt; powiedzie się, to &amp;lt;tt&amp;gt;wczytaj_z_serwera()&amp;lt;/tt&amp;gt; nie zostanie użyte. Niezależnie od tego którym sposobem uzyskaliśmy obrazek, zostaje on w końcu wyświetlony przy użyciu funkcji &amp;lt;tt&amp;gt;wyswietl()&amp;lt;/tt&amp;gt;. &lt;br /&gt;
Jak już wspominaliśmy, wyjątek jest obiektem. W konstrukcji &amp;lt;tt&amp;gt;except  &amp;lt;typ-wyjątku&amp;gt; as &amp;lt;nazwa-zmiennej&amp;gt;:&amp;lt;/tt&amp;gt; wiążemy ten przechwycony obiekt z nazwą &amp;lt;tt&amp;gt;nazwa-zmiennej&amp;lt;/tt&amp;gt;. Dzięki temu możemy z tym obiektem coś zrobić. W naszym przykładzie funkcja &amp;lt;tt&amp;gt;zapisz_do_dziennika()&amp;lt;/tt&amp;gt; jako jeden z argumentów dostaje przechwycony wyjątek aby odnotować fakt i okoliczności jego wystąpienia w pliku dziennika.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Rzucanie wyjątków jest faktycznie bardzo proste i zostało powyżej opisane w sposób w miarę kompletny. Natomiast obsługa wyjątków jest bardziej rozbudowana i dopuszcza następujące typy reakcji:&lt;br /&gt;
&lt;br /&gt;
* Po pierwsze, możemy chwytać na raz wiele różnych typów wyjątków i obsługiwać je w ten sam sposób. &lt;br /&gt;
* Po drugie, możemy chwytać wiele różnych typów wyjątków i obsługiwać je w różny sposób. &lt;br /&gt;
* Po trzecie, możemy chwytać wyjątki wszystkich typów. &lt;br /&gt;
* Po czwarte, możemy napisać kod, który zostanie wykonany jeśli nie został rzucony wyjątek, ale poza obszarem łapania wyjątków.&lt;br /&gt;
* Po piąte, możemy napisać kod który zostanie wykonany niezależnie od tego czy program wykonał się normalnie czy został rzucony wyjątek. &lt;br /&gt;
  [przypis: o BaseException i przyjaciołach]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang= python&amp;gt;&lt;br /&gt;
try:&lt;br /&gt;
    &amp;lt;operacje-mogące-rzucić-wyjątek&amp;gt;&lt;br /&gt;
except &amp;lt;typ-wyjątku&amp;gt; as &amp;lt;nazwa-zmiennej&amp;gt;:&lt;br /&gt;
    # po pierwsze&lt;br /&gt;
    &amp;lt;operacje-zaradcze&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    # Tutaj przechwytujemy wyjątek jednego określonego typu.&lt;br /&gt;
&lt;br /&gt;
    # Istnieje też starsza notacja (Python &amp;lt;= 2.5 ?), gdzie&lt;br /&gt;
    # zamiast 'as' używa się przecinka. Jej wadą mniejsza&lt;br /&gt;
    # ekspresyjność i możliwość pomylenia sytuacji gdy&lt;br /&gt;
    # chcielibyśmy przechwycić dwa różne typy wyjątków (patrz&lt;br /&gt;
    # poniżej) bez zachowywania wyjątku do zmiennej, z sytuacją&lt;br /&gt;
    # taką jak tutaj, gdzie chcemy przechwycić wyjątek określonego&lt;br /&gt;
    # typu i zachować go do zmiennej.&lt;br /&gt;
except &amp;lt;typ-wyjątku-1&amp;gt;, &amp;lt;typ-wyjątku-2&amp;gt; as &amp;lt;nazwa-zmiennej&amp;gt;:&lt;br /&gt;
    # po drugie&lt;br /&gt;
    &amp;lt;operacje-zaradcze&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    # Tutaj przechwytujemy wyjątek typu typ-wyjątku-1&lt;br /&gt;
    # lub typ-wyjątku-2.&lt;br /&gt;
except Exception:&lt;br /&gt;
    # po trzecie&lt;br /&gt;
    &amp;lt;operacje-zaradcze&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    # Tutaj przechwytujemy wyjątek każdego podtypu Exception.&lt;br /&gt;
else:&lt;br /&gt;
    # po czwarte&lt;br /&gt;
    &amp;lt;operacje-wykonywane-w-przypadku-powodzenia&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    # Tutaj należy wpisać kod który jest kontynuacją&lt;br /&gt;
    # &amp;lt;operacji-mogących-rzucić-wyjątek&amp;gt;. Napisanie go w tym miejscu&lt;br /&gt;
    # powoduje, że wyjątek rzucony tutaj nie zostanie złapany.&lt;br /&gt;
finally:&lt;br /&gt;
    # po piąte&lt;br /&gt;
    &amp;lt;operacje-wykonywane-zawsze&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    # Tutaj należy wpisać działania takie jak zamknięcie plików&lt;br /&gt;
    # i zwolnienie blokad, które muszą być wykonane niezależnie&lt;br /&gt;
    # od tego czy operacja się powiodła czy też nie.&lt;br /&gt;
    # Innym mechanizmem, który może często zastąpić taki blok&lt;br /&gt;
    # else, jest konstrukcja 'with'.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
W wypadku gdy wykorzystamy gołe &amp;lt;tt&amp;gt;except:&amp;lt;/tt&amp;gt;, powinniśmy zachować dużą dozę ostrożności.&lt;br /&gt;
W ten sposób przechwycimy np. wyjątki typu &amp;lt;tt&amp;gt;ValueError&amp;lt;/tt&amp;gt; związane z niewłaściwym wywołaniem funkcji gdzieś w kodzie. Ale przechwycimy także wszystkie inne wyjątki, nawet takie których się nie spodziewaliśmy. W tym miejscu często programiści wypisują komunikat o błędzie, a następnie ponownie rzucają ten sam wyjątek aby był dostępny dla kolejnych w hierarchii funkcji  (zob. przykład w&lt;br /&gt;
[http://docs.python.org/tutorial/errors.html#handling-exceptions podręczniku Pythona]).&lt;br /&gt;
&lt;br /&gt;
'''Przykład wykonywalny:'''&lt;br /&gt;
&amp;lt;source lang= python&amp;gt;&lt;br /&gt;
# -*- coding: utf-8 -*-&lt;br /&gt;
# plik exc1.py&lt;br /&gt;
import random, time&lt;br /&gt;
&lt;br /&gt;
try:&lt;br /&gt;
    print 'Zaczynam obliczenia... ',&lt;br /&gt;
    time.sleep(3 * random.random())&lt;br /&gt;
    print 'obliczenia trwają... ',&lt;br /&gt;
    wybor = random.randrange(0, 5)&lt;br /&gt;
    if wybor == 0:&lt;br /&gt;
         print 'wykonamy dzielenie przez 0'&lt;br /&gt;
         print 1 / 0&lt;br /&gt;
         print 'udało się :)'&lt;br /&gt;
    elif wybor == 1:&lt;br /&gt;
         print 'rzucimy wyjątek dzielenia przez zero samemu'&lt;br /&gt;
         raise ZeroDivisionError('jak mogłaś?')&lt;br /&gt;
         print 'znowu się udało :)'&lt;br /&gt;
    elif wybor == 2:&lt;br /&gt;
         print 'rzucimy jeszcze inny wyjątek'&lt;br /&gt;
         raise ValueError('wylosowałeś krótką słomkę')&lt;br /&gt;
         print 'udało się ponownie :)'&lt;br /&gt;
    else:&lt;br /&gt;
         print '...obliczenia zakończone!'&lt;br /&gt;
except ValueError as e:&lt;br /&gt;
    print &amp;quot;Wiem co było źle podczas obliczeń:&amp;quot;, e&lt;br /&gt;
    raise&lt;br /&gt;
except ArithmeticError as e: # obejmuje ZeroDivisionError&lt;br /&gt;
    print &amp;quot;Coś było źle podczas obliczeń.&amp;quot;&lt;br /&gt;
    import sys&lt;br /&gt;
    print &amp;quot;Napotkałem taki błąd:&amp;quot;, sys.exc_info()[1]&lt;br /&gt;
    raise   # użycie tej instrukcji wytwarza sytuację wyjątkową taką,&lt;br /&gt;
            # jaka zdarzyła się ostatnio&lt;br /&gt;
            # czyli rzuca wyjątek taki, jaki właśnie przechwyciliśmy&lt;br /&gt;
else:&lt;br /&gt;
    print &amp;quot;Obliczenia przebiegły pomyślnie.&amp;quot;&lt;br /&gt;
finally:&lt;br /&gt;
    print &amp;quot;Koniec bloku try-except-else-finally.&amp;quot;&lt;br /&gt;
print &amp;quot;What's next?&amp;quot;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Jeśli zachowamy ten przykład do pliku &amp;lt;tt&amp;gt;exc1.py&amp;lt;/tt&amp;gt; to możemy &lt;br /&gt;
wykonywać go wielokrotnie i patrzeć na wypisywane komunikaty.&lt;br /&gt;
W szczególności te zakończone śmieszkiem nigdy nie zostaną wypisane :). &lt;br /&gt;
Z drugiej strony komunikat o końcu bloku zostanie wypisany zawsze.&lt;br /&gt;
&lt;br /&gt;
== Hierarchia wyjątków ==&lt;br /&gt;
[[Image:Exception-hierarchy.svg]]&lt;br /&gt;
&lt;br /&gt;
== Inne sposoby ==&lt;br /&gt;
Nie wszystkie języki programowania mają mechanizm wyjątków, nie zawsze też wyjątki są właściwym sposobem obsługi błędów. W zależności od sytuacji wykorzystywane jest parę mechanizmów które warto znać. Są one pokrótce opisane poniżej.&lt;br /&gt;
&lt;br /&gt;
=== Zwracanie zarezerwowanej wartości ===&lt;br /&gt;
Ustalamy, że pewna szczególna wartość oznacza błąd.&lt;br /&gt;
Np. w przypadku wczytywaniu obrazków, wynik poprawny jest jakimś obiektem. Możemy wobec tego umówić się, że wynik &amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt; oznacza błąd — niemożność wczytania obrazka.&lt;br /&gt;
&lt;br /&gt;
Po wykonaniu operacji mogącej zwrócić wartość szczególną aby zasygnalizować błąd, trzeba sprawdzić czy uzyskaliśmy normalny wynik, czy też nie.&lt;br /&gt;
&amp;lt;source lang= python&amp;gt;&lt;br /&gt;
def wyswietl_obrazek(nazwa):&lt;br /&gt;
  obrazek = wczytaj_z_przechowalni(nazwa)&lt;br /&gt;
  if obrazek is None:&lt;br /&gt;
    zapisz_do_dziennika('nie udało się odczytać z przechowalni:' + nazwa)&lt;br /&gt;
    obrazek = wczytaj_z_serwera(nazwa)&lt;br /&gt;
  wyswietl(obrazek)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Zwracanie wielu zarezerwowanych wartości ===&lt;br /&gt;
&amp;lt;source lang= python&amp;gt;&lt;br /&gt;
  def wyswietl_obrazek(nazwa):&lt;br /&gt;
    obrazek = wczytaj_z_przechowalni(nazwa)&lt;br /&gt;
    if obrazek.kod == PUSTY_OBRAZEK:&lt;br /&gt;
      zapisz_do_dziennika('obrazka nie ma w przechowalni:' + nazwa)&lt;br /&gt;
      obrazek = wczytaj_z_serwera(nazwa)&lt;br /&gt;
    elif obrazek.kod == ZLY_OBRAZEK:&lt;br /&gt;
      zapisz_do_dziennika('obrazek z przechowalni jest niepoprawny:' + nazwa)&lt;br /&gt;
      obrazek = wczytaj_z_serwera(nazwa)&lt;br /&gt;
    wyswietl(obrazek)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ten typ zwracania informacji o błędzie jest używany zwłaszcza wtedy, gdy jest potrzebne dużo możliwych wartości świadczących o niepowodzeniu, a tylko jedna świadcząca o powodzeniu operacji. Powłoka UNIXowa używa konwencji takiej, że programy zwracają 0 jeśli udało im się wykonać poprawnie, a każda inna wartość oznacza błąd. Możliwych błędów jest dużo: brak pliku na którym miała być wykonana operacja, brak pozwolenia, przerwanie operacji przez użytkownika, ...&lt;br /&gt;
&lt;br /&gt;
=== Zwracanie jednej zarezerwowanej wartości i przechowywanie informacji w zmiennej globalnej ===&lt;br /&gt;
Najbardziej znane użycie tego mechanizmu to zmienna &amp;lt;tt&amp;gt;errno&amp;lt;/tt&amp;gt; używana przy wywoływaniu funkcji systemowych w języku C (takich jak &amp;lt;tt&amp;gt;open&amp;lt;/tt&amp;gt; do otwierania plików czy &amp;lt;tt&amp;gt;execve&amp;lt;/tt&amp;gt; do wywołania innego programu). W wypadku niepowodzenia, wywołanie funkcji  zwraca szczególną wartość (–1), a do globalnej zmiennej &amp;lt;tt&amp;gt;errno&amp;lt;/tt&amp;gt; (od numer błędu, ang. ''error number'') zostaje zapisany kod błędu. Program może następnie zajrzeć do tablicy opisów błędów i wydrukować komunikat dla użytkownika.&lt;br /&gt;
&lt;br /&gt;
Wadą tej metody jest to, że zmienna &amp;lt;tt&amp;gt;errno&amp;lt;/tt&amp;gt; jest jedna. Bezpośrednio po wywołaniu funkcji, przed wywołaniem jakiejkolwiek funkcji systemowej, musimy ją zapisać w inne miejsce, tak by nie uległa nadpisaniu w przypadku kolejnego błędu. Generalnie taka obsługa błędów jest bardzo natrętna — po każdym wywołaniu funkcji systemowej musi być parę linijek sprawdzających, czy wartość zwrócona przez funkcję nie świadczy o błędzie, i ewentualnie jaki jest to błąd.&lt;br /&gt;
&lt;br /&gt;
=== Natychmiastowe kończenie programu ===&lt;br /&gt;
Takie zachowanie — wyświetlenie komunikatu i zakończeniu programu — jest bardzo złym wyjściem gdy zostanie użyte w bibliotece lub kodzie który może być wywołany z więcej niż jednego miejsca. Wynika to z tego, że takie „zaszycie” zachowania w miejscu wykrycia błędu silnie ogranicza możliwości użycia danej funkcji.&lt;br /&gt;
&lt;br /&gt;
Niemniej, jeśli piszemy program od początku do końca i nie zależy nam na ponownym wykorzystaniu tego kodu, to jest to rozwiązanie proste, zwięzłe i szybkie.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang= python&amp;gt;&lt;br /&gt;
def wyswietl_obrazek(nazwa):&lt;br /&gt;
    &amp;quot;Odczytaj obrazek z dysku i wyświetl. Niepowodzenie kończy program.&amp;quot;&lt;br /&gt;
    obrazek = wczytaj_z_dysku(nazwa)&lt;br /&gt;
    if obrazek is None:&lt;br /&gt;
       import sys&lt;br /&gt;
       print 'nie udało się odczytać:' + nazwa)&lt;br /&gt;
       sys.exit(1)&lt;br /&gt;
    wyswietl(obrazek)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
W tym przykładzie użyte są dwie konwencje — funkcja &amp;lt;tt&amp;gt;wczytaj_z_dysku&amp;lt;/tt&amp;gt; w przypadku błędu zwraca wartość szczególną (&amp;lt;tt&amp;gt;None&amp;lt;/tt&amp;gt;), natomiast funkcja wywołująca &amp;lt;tt&amp;gt;wyswietl_obrazek&amp;lt;/tt&amp;gt; w reakcji na ten błąd kończy program.&lt;br /&gt;
&lt;br /&gt;
Zastosowanie tego sposobu obsługi błędów ma jeszcze jeden aspekt, który w praktyce okazuje się kłopotliwy, niezależnie od tego, czy zakończeniu programu jest właściwym wyjściem. Przed zakończeniem programu informujemy wypisując komunikat o błędzie na standardowe wyjście. Co się stanie jeśli w pewnym momencie dodamy interfejs graficzny do naszego programu który pozwoli na wywołanie programu nie z konsoli, ale z graficznego menu? Komunikaty wypisywane na konsolę ulegną zagubieniu, bo w sytuacji użycia graficznego interfejsu użytkownika (GUI), właściwym mechanizmem komunikacji z użytkownikiem jest wyświetlenie okienka. Programista dodający GUI musiałby przejść program i zmienić wszystkie miejsca gdzie &amp;lt;tt&amp;gt;print&amp;lt;/tt&amp;gt; zostaje użyte do wypisania błędu, lub też spowodować, że wszystkie użycia &amp;lt;tt&amp;gt;print&amp;lt;/tt&amp;gt; prowadzą do wyświetlenia komunikatu również w GUI.&lt;br /&gt;
&lt;br /&gt;
=== Wywoływanie funkcji do obsługi błędów ===&lt;br /&gt;
Bardzo ogólnym mechanizmem obsługi błędów jest oddelegowanie obsługi z powrotem do strony wywołującej. W momencie wywołania funkcji bibliotecznej, jako parametr podajemy funkcję (z ang. ''handler''), która zostanie wywołana w wypadku wystąpienia błędu. Decyzja o sposobie obsługi błędu zostaje wtedy podjęta wewnątrz funkcji ''handler'' — np. nie ma żadnych ograniczeń na to jak (i czy) komunikat o błędzie będzie wypisany. Funkcja ''handler'' zwraca kod, na podstawie którego działanie funkcji w której wystąpił błąd jest kontynuowane lub przerywane.&lt;br /&gt;
&lt;br /&gt;
Silnym plusem jest tutaj możliwość kontynuowania obliczeń. Silnym minusem jest inwazyjność tej metody i konieczność napisania wyspecjalizowanej funkcji do obsługi błędów.&lt;br /&gt;
&lt;br /&gt;
Jako przykład mogą posłużyć powiązane funkcje [http://docs.scipy.org/doc/numpy/reference/generated/numpy.seterr.html &amp;lt;tt&amp;gt;numpy.seterr&amp;lt;/tt&amp;gt;] i&lt;br /&gt;
[http://docs.scipy.org/doc/numpy/reference/generated/numpy.seterrcall.html &amp;lt;tt&amp;gt;numpy.seterrcall&amp;lt;/tt&amp;gt;]. Pierwsza z nich może być użyta do ustawienia jako obsługę błędów wywołania funkcji zarejestrowanej przy pomocy drugiej z nich. Funkcja zarejestrowana jako obsługa błędów otrzymuje w momencie wywołania informację o błędzie i może wypisać komunikat i ewentualnie rzucić wyjątek. Jeśli wyjątek nie zostanie rzucony, obliczenia są kontynuowane.&lt;br /&gt;
&lt;br /&gt;
== Wyjątki kontra inne mechanizmy błędów ==&lt;br /&gt;
Python jest językiem w którym mechanizm wyjątków jest szczególnie szeroko wykorzystywany. Wynika to po części z tego, że konstrukcja &amp;lt;tt&amp;gt;try...except&amp;lt;/tt&amp;gt; jest wydajna, tak że nie ma sensu (z punktu szybkości działania programu), prewencyjnie sprawdzać czy jakiś warunek jest spełniony, by uniknąć przechwytywania wyjątku. Jest to ujęte zwięźle w zaleceniu dla pythonistów&lt;br /&gt;
  Easier to ask for forgiveness than permission&lt;br /&gt;
&lt;br /&gt;
Rozpowszechnione użycie wyjątków ma też tę zaletę, że pominięcie obsługi błędów prowadzi, w przypadku niepoprawnego działania programu, do jego szybkiego zakończenia i wypisania ciągu wywołań funkcji w programie (ang. ''stack trace''). Nie jest to może rozwiązanie najbardziej eleganckie, często też komunikat jest niezrozumiały dla nie-programistów, ale generalnie jest to znacznie lepsze wyjście niż dalsze wykonywanie programu.&lt;br /&gt;
&lt;br /&gt;
Jak każdy ogólny mechanizm, wyjątki nie są panaceum, tylko jednym z mechanizmów do użycia w połączeniu z innymi w zależności od sytuacji. Program przeznaczony dla końcowego użytkownika powinien gdzieś na wysokim poziomie zawierać blok &amp;lt;tt&amp;gt;try...except&amp;lt;/tt&amp;gt; przechwytujący większość wyjątków. Użytkownik powinien zostać poinformowany o zaistniałej sytuacji w możliwie łagodnych słowach. Następnie powinien zostać użyty inny z wymienionych mechanizmów, zapewne po prostu zakończenie programu.&lt;br /&gt;
&lt;br /&gt;
Podobnie jeśli mamy program wykonujący długotrwałe obliczenia numeryczne, i w jednym z 10000 punktów siatki obliczenia zakończą się rzuceniem wyjątku, to zakończenie działania programu zapewne nie jest rozwiązaniem preferowanym przez użytkownika. Należy zapewne zapisać wartość szczególną (&amp;lt;tt&amp;gt;NaN&amp;lt;/tt&amp;gt; ?), wypisać komunikat, i kontynuować obliczenia.&lt;br /&gt;
&lt;br /&gt;
== Przykłady ==&lt;br /&gt;
&lt;br /&gt;
=== Przechowywanie wyniku długotrwałych obliczeń ===&lt;br /&gt;
Załóżmy, że chcemy w celu optymalizacji wykonywać funkcję&lt;br /&gt;
obliczeniową tylko raz dla każdego zestawu argumentów.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang= python&amp;gt;&lt;br /&gt;
def _funkcja(argument):&lt;br /&gt;
   &amp;quot;Ta funkcja symuluje długotrwałe, trudne symuluacje.&amp;quot;&lt;br /&gt;
   import time, random&lt;br /&gt;
   time.sleep(3)&lt;br /&gt;
   wynik = random.random()&lt;br /&gt;
   return wynik&lt;br /&gt;
&lt;br /&gt;
_cache = {}&lt;br /&gt;
&lt;br /&gt;
def funkcja(argument):&lt;br /&gt;
   try:&lt;br /&gt;
      return _cache[argument]&lt;br /&gt;
   except KeyError:&lt;br /&gt;
      wynik = _cache[argument] = _funkcja(argument)&lt;br /&gt;
      return wynik&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Tutaj przedrostek &amp;lt;tt&amp;gt;_&amp;lt;/tt&amp;gt;, zgodnie z powszechnie przyjętą w Pythonie konwencją, oznacza funkcję lub zmienną ''prywatną'' — element implementacji, do którego nie należy odwoływać się spoza tego modułu. Interfejs publiczny to funkcja &amp;lt;tt&amp;gt;funkcja&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Zaglądanie do słownika ===&lt;br /&gt;
Załóżmy, że chcemy zwrócić wartość ze słownika, jeśli&lt;br /&gt;
tam jest, a w przeciwnym wypadku obliczyć domyślną wartość dla danego klucza.&lt;br /&gt;
&lt;br /&gt;
Tak nie należy (wersja LOOK BEFORE YOU LEAP &amp;amp;mdash; spójrz zanim skoczysz):&lt;br /&gt;
&amp;lt;source lang= python&amp;gt;&lt;br /&gt;
if key in dictionary:&lt;br /&gt;
    return dictionary[key]&lt;br /&gt;
else:&lt;br /&gt;
    return compute_default_value_for(key)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To, że tak nie należy, wynika z faktu, że jeśli słownik jest wystarczająco duży, to najbardziej pracochłonna operacja zostanie wykonana dwa razy. Tą operacją jest przeszukanie słownika, by znaleźć odpowiedni klucz — niezależnie czy się uda go znaleźć, czy nie, zajmuje to tyle samo czasu.&lt;br /&gt;
&lt;br /&gt;
Należy po prostu spróbować (wersja EASIER TO ASK FOR FORGIVENESS THAN PERMISSION &amp;amp;mdash; łatwiej prosić o wybaczenie niż o pozwolenie):&lt;br /&gt;
&amp;lt;source lang= python&amp;gt;&lt;br /&gt;
try:&lt;br /&gt;
    return dictionary[key]&lt;br /&gt;
except KeyError:&lt;br /&gt;
    return compute_default_value_for(key)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[category:Programowanie z Pythonem]]&lt;br /&gt;
&lt;br /&gt;
== Dostęp do pliku ==&lt;br /&gt;
Załóżmy, że napisaliśmy prosty programik liczący linijki komentarza (zaczynające się od znaku &amp;lt;tt&amp;gt;#&amp;lt;/tt&amp;gt;) w pliku.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang= python&amp;gt;&lt;br /&gt;
# komentarze.py&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
file = open(sys.argv[1])&lt;br /&gt;
count = 0&lt;br /&gt;
for line in file:&lt;br /&gt;
    count += line.startswith('#')&lt;br /&gt;
&lt;br /&gt;
print 'liczba linijek z komentarzem =', count&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Czy ten program ma jakąkolwiek obsługę błędów? Explicite nie, ale dzięki temu, że funkcje wbudowane w Pythona (funkcje biblioteczne) rzucają wyjątki w&amp;amp;nbsp;przypadku niepowodzenia, program zachowa się poprawnie w&amp;amp;nbsp;przypadku wystąpienia różnego rodzaju sytuacji nieprzewidzianych. Nawet jeśli komunikat nie będzie doszlifowany, to będzie zawierał informacje pozwalające (programiście) na rozwiązanie problemu. Zobaczmy:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang='shell_example'&amp;gt;&lt;br /&gt;
# wywołanie poprawne&lt;br /&gt;
$ python komentarze.py uni1.py&lt;br /&gt;
liczba linijek z komentarzem = 1&lt;br /&gt;
&lt;br /&gt;
# wywołanie na pliku którego nie ma&lt;br /&gt;
$ python komentarze.py xxx.py&lt;br /&gt;
Traceback (most recent call last):&lt;br /&gt;
  File &amp;quot;komentarze.py&amp;quot;, line 3, in &amp;lt;module&amp;gt;&lt;br /&gt;
    file = open(sys.argv[1])&lt;br /&gt;
IOError: [Errno 2] No such file or directory: 'xxx.py'&lt;br /&gt;
#                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^&lt;br /&gt;
&lt;br /&gt;
# wywołanie na pliku którego nie wolno odczytać&lt;br /&gt;
$ python komentarze.py /etc/shadow&lt;br /&gt;
Traceback (most recent call last):&lt;br /&gt;
  File &amp;quot;komentarze.py&amp;quot;, line 3, in &amp;lt;module&amp;gt;&lt;br /&gt;
    file = open(sys.argv[1])&lt;br /&gt;
IOError: [Errno 13] Permission denied: '/etc/shadow'&lt;br /&gt;
#                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^&lt;br /&gt;
&lt;br /&gt;
# wywołanie bez wymaganego argumentu&lt;br /&gt;
$ python komentarze.py&lt;br /&gt;
Traceback (most recent call last):&lt;br /&gt;
  File &amp;quot;komentarze.py&amp;quot;, line 3, in &amp;lt;module&amp;gt;&lt;br /&gt;
    file = open(sys.argv[1])&lt;br /&gt;
IndexError: list index out of range&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Widać, że program wypisuje wynik tylko wtedy, gdy ten wynik jest poprawny.&lt;br /&gt;
&lt;br /&gt;
Nawet w ostatnim przypadku, gdy komunikat jest mniej jasny, można łatwo się domyślić (jeśli się wie że &amp;lt;tt&amp;gt;sys.argv&amp;lt;/tt&amp;gt; to lista argumentów programu), że lista argumentów programu jest za krótka.&lt;br /&gt;
&lt;br /&gt;
Oczywiście znacznie lepiej, by programista sprawdził, czy użytkownik podał właściwą listę argumentów do programu. W szczególności w obecnej wersji, nadmiarowe argumenty są ignorowane, co stoi w sprzeczności z zasadą, że&lt;br /&gt;
''errors should never pass silently'', czyli że żadne błędy nie powinny uchodzić uwadze.&lt;br /&gt;
Niemniej, wydaje mi się, że ten przykład ładnie pokazuje elegancję wyjątków.&lt;br /&gt;
&lt;br /&gt;
== Sprzątanie po sobie ==&lt;br /&gt;
W części [[#Jak działają wyjątki w Pythonie - chwytanie|o chwytaniu]] wyjątków został pokazany blok &amp;lt;tt&amp;gt;finally&amp;lt;/tt&amp;gt;. Do czego on służy? Kiedy należy go użyć?&lt;br /&gt;
&lt;br /&gt;
Komendy zawarte w bloku &amp;lt;tt&amp;gt;finally&amp;lt;/tt&amp;gt; są wykonywane zawsze, niezależnie od tego, czy wyjątek został rzucony, czy nie.&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
Jeśli blok &amp;lt;tt&amp;gt;try&amp;lt;/tt&amp;gt; wykonał się bez problemu, to komendy w bloku &amp;lt;tt&amp;gt;finally&amp;lt;/tt&amp;gt; (i potem &amp;lt;tt&amp;gt;else&amp;lt;/tt&amp;gt;) są wykonywane normalnie. Jeśli natomiast w obszarze bloku &amp;lt;tt&amp;gt;try&amp;lt;/tt&amp;gt; zostanie rzucony wyjątek,&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
Pozwala to na zawarcie w tym bloku operacji typu „sprzątanie po sobie”, które muszą zawsze zostać wykonane. Typowy przykład to sytuacja, gdzie procesy działające równolegle muszą się ze sobą synchronizować i wykorzystują do tego celu blokadę. Może to być np. pusty plik na dysku, który zostaje stworzony przed rozpoczęciem działań i skasowany po ich zakończeniu, tzw. ''lock-file''.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang= python&amp;gt;&lt;br /&gt;
import sys, time&lt;br /&gt;
&lt;br /&gt;
def create(lockfile):&lt;br /&gt;
    while True:&lt;br /&gt;
        try:&lt;br /&gt;
    	    os.open(lockfile, os.O_CREAT|os.O_EXCL|os.O_RDONLY)&lt;br /&gt;
            break&lt;br /&gt;
        except OSError as e:&lt;br /&gt;
            if e.errno != os.errno.EEXIST:&lt;br /&gt;
                raise&lt;br /&gt;
            print 'file is locked!, waiting'&lt;br /&gt;
            time.sleep(1)&lt;br /&gt;
&lt;br /&gt;
def remove(lockfile):&lt;br /&gt;
    os.unlink(lockfile)&lt;br /&gt;
&lt;br /&gt;
def do_work(datafile):&lt;br /&gt;
    lockfile = datafile + '.lock'&lt;br /&gt;
    create(lockfile)&lt;br /&gt;
    try:&lt;br /&gt;
	do_some_work_on(datafile)&lt;br /&gt;
    finally:&lt;br /&gt;
	remove(lockfile)&lt;br /&gt;
&lt;br /&gt;
if __name__ == '__main__'&lt;br /&gt;
   do_work(sys.argv[1])&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Jak widać, ten program jest napisany tak, że jeśli w momencie wywołania będzie istniał plik &amp;lt;tt&amp;gt;lockfile&amp;lt;/tt&amp;gt;, to program w nieskończoność będzie czekał na jego zniknięcie. Dlatego kluczowe jest, by uruchomienie programu zawsze zostało zakończone skasowaniem pliku &amp;lt;tt&amp;gt;lockfile&amp;lt;/tt&amp;gt;. Programista nie przywidywał wystąpienia żadnego konkretnego błędu w wywołaniu &amp;lt;tt&amp;gt;do_some_work_on&amp;lt;/tt&amp;gt;, wyjątek rzucony w trakcie wykonywania spowoduje zakończeniu programu i wypisanie ciągu wywołań w programie. Niemniej, nawet przed takim smutnym zakończeniem, plik &amp;lt;tt&amp;gt;lockfile&amp;lt;/tt&amp;gt; zostanie usunięty.&lt;br /&gt;
&lt;br /&gt;
Jako nieco łatwiejszy przykład możemy rozważyć sytuację, gdy chcemy zamknąć otwarty plik zaraz po zakończeniu pewnego ciągu instrukcji.&lt;br /&gt;
W przykładzie powyżej (zob. [[#Pliki]]) zamykaliśmy plik explicite, używając jego metody &amp;lt;tt&amp;gt;close&amp;lt;/tt&amp;gt;. Jest to jak najbardziej wystarczające, bo chodzi nam o jego zamknięcie tylko dlatego, by przy okazji wypchnąć zmiany w nim dokonane i móc go znowu za chwilę otworzyć i odczytać nową zawartość. Normalnie plik i tak zostałby zamknięty w momencie zakończenia programu. Wobec tego nie ma sensu przejmować się wystąpieniem wyjątku w operacjach wykonywanych na otwartym pliku (czyli pojedynczej operacji &amp;lt;tt&amp;gt;os.write(wierszyk)&amp;lt;/tt&amp;gt;), bo on i tak uniemożliwiłby wykonanie dalszej części programu. Ale załóżmy, że chcemy, by metoda &amp;lt;tt&amp;gt;close&amp;lt;/tt&amp;gt; została wykonana niezależnie od tego, co zdarzy się w trakcie &amp;lt;tt&amp;gt;os.write&amp;lt;/tt&amp;gt;. Możemy zawrzeć wywołanie &amp;lt;tt&amp;gt;close&amp;lt;/tt&amp;gt; w bloku &amp;lt;tt&amp;gt;finally&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang= python&amp;gt;&lt;br /&gt;
f1 = open('wierszyk.txt', 'w')&lt;br /&gt;
try:&lt;br /&gt;
    f1.write(wierszyk)&lt;br /&gt;
finally:&lt;br /&gt;
    f1.close()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Sprzątanie zestandaryzowane ==&lt;br /&gt;
Nowsze wersje Pythona (&amp;amp;ge; 2.5) zawierają konstrukcję &amp;lt;tt&amp;gt;with&amp;lt;/tt&amp;gt; pozwalającą na wygodne skorzystanie z  predefiniowanych operacji do wywołania przed i&amp;amp;nbsp;po jakimś bloku kodu. Istotne jest to, że tak jak w&amp;amp;nbsp;przypadku bloku &amp;lt;tt&amp;gt;finally&amp;lt;/tt&amp;gt;, operacje kończące są wywoływane nawet w wypadku wystąpienia wyjątku.&lt;br /&gt;
&lt;br /&gt;
Operacja &amp;lt;tt&amp;gt;close&amp;lt;/tt&amp;gt; na pliku wywoływana w bloku &amp;lt;tt&amp;gt;finally&amp;lt;/tt&amp;gt; jest bardzo powszechna, chociaż może nie tak jak iteracja po linijkach w pliku. Dlatego klasa &amp;lt;tt&amp;gt;file&amp;lt;/tt&amp;gt; definiuje ją jako standardową operację „sprzątającą”.&lt;br /&gt;
&lt;br /&gt;
Przykład powyżej przepisany z&amp;amp;nbsp;wykorzystaniem konstrukcji &amp;lt;tt&amp;gt;with&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&amp;lt;source lang= python&amp;gt;&lt;br /&gt;
with open('wierszyk.txt', 'w') as f1:&lt;br /&gt;
    f1.write(wierszyk)&lt;br /&gt;
    # po wyjściu z tego bloku plik zostanie samoczynnie zamknięty&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
W nowych programach należy postępować w ten właśnie sposób.&lt;br /&gt;
&lt;br /&gt;
W jaki sposób klasa &amp;lt;tt&amp;gt;file&amp;lt;/tt&amp;gt; definiuje, co ma zostać wywołane na końcu bloku &amp;lt;tt&amp;gt;with&amp;lt;/tt&amp;gt;? Wykorzystuje ''context manager protocol'' opisany w&lt;br /&gt;
[http://www.python.org/dev/peps/pep-0343/ PEP 0343].&lt;/div&gt;</summary>
		<author><name>Jarekz</name></author>
		
	</entry>
</feed>