Wypróbuj Pythona z wyjątkiem: wyjaśniono w przykładach

Photo of author

By maciekx

W języku Python, konstrukcja `try…except` umożliwia eleganckie zarządzanie sytuacjami wyjątkowymi, zapobiegając nagłym przerwaniom działania programu.

Dzięki obsłudze wyjątków, kod staje się bardziej solidny i odporny na błędy. Ten artykuł zagłębia się w mechanizmy obsługi wyjątków, prezentując typowe scenariusze, gdzie jest ona nieoceniona. Dodatkowo, wyjaśnimy, jak samodzielnie wywoływać wyjątki.

Czym jest obsługa wyjątków?

Wyjątki to poważne nieprawidłowości lub błędy, które mogą pojawić się podczas działania programu. Jeżeli nie zostaną właściwie obsłużone, mogą doprowadzić do jego nieoczekiwanego zakończenia. Obsługa wyjątków to strategia zarządzania takimi sytuacjami, która ma na celu utrzymanie programu w działaniu pomimo wystąpienia problemów.

Spójrzmy na prosty przykład, który ilustruje istotę wyjątku:

user_input = input("Wprowadź liczbę: ")
num = int(user_input)
print("Twoja liczba podwojona to:", num * 2)

Na pierwszy rzut oka powyższy kod wydaje się nieskomplikowany. Pobiera on dane od użytkownika, konwertuje je na liczbę całkowitą, a następnie wyświetla podwojoną wartość.

Gdy program otrzyma na wejściu liczbę, na przykład 5, działa bez zarzutu. Wynik jest następujący:

Problem pojawia się, gdy zamiast liczby, użytkownik wprowadzi na przykład słowo „cześć”. W takiej sytuacji program zakończy swoje działanie z powodu błędu. Napis „cześć” nie da się przekształcić na liczbę całkowitą, co powoduje wywołanie wyjątku i zatrzymanie programu.

Dlaczego wyjątki są zgłaszane i jak należy z nimi postępować?

Wyjątki są zgłaszane, ponieważ podczas tworzenia programów często dzielimy je na mniejsze, niezależne funkcje. Te funkcje wykonują określone zadania, a następnie są wywoływane w odpowiedniej kolejności.

W przedstawionym wcześniej przykładzie, funkcja `input` pobiera dane od użytkownika, funkcja `int` konwertuje te dane na liczbę całkowitą, a funkcja `print` wyświetla wynik.

Podczas swojej pracy, funkcje mogą napotkać sytuacje, z którymi nie potrafią sobie poradzić. W takiej sytuacji muszą przerwać swoje działanie i poinformować o wystąpieniu błędu. Do tego celu służy właśnie zgłaszanie wyjątków.

Kod, który wywołuje taką funkcję, ma za zadanie „nasłuchiwać” na zgłoszone wyjątki i odpowiednio na nie reagować. Jeśli wyjątki nie zostaną obsłużone, program zakończy działanie z błędem, tak jak widzieliśmy to w poprzednim przykładzie.

Zatem wyjątki są mechanizmem komunikacji, który pozwala wywołanej funkcji poinformować kod, który ją wywołał, o zaistniałym problemie. Właściwa reakcja na te sygnały alarmowe to właśnie istota obsługi wyjątków.

Różne rodzaje wyjątków

Trzeba pamiętać, że nie wszystkie wyjątki są takie same. Różne rodzaje błędów wywołują różne rodzaje wyjątków. Przykładowo, próba podzielenia liczby przez zero spowoduje wywołanie wyjątku `ZeroDivisionError`. Błąd typu danych podczas wykonywania operacji wywoła wyjątek `TypeError`. Pełną listę dostępnych wyjątków znajdziesz w dokumentacji Pythona.

Jak obsługiwać wyjątki

Wyjątki to, jak już wspomnieliśmy, sygnały o błędach wysyłane przez wywoływane funkcje. Nasz kod powinien więc nasłuchiwać tych sygnałów i właściwie na nie reagować. W tym celu używamy w Pythonie konstrukcji `try…except`. Jej podstawowa forma wygląda następująco:

try:
    # Kod, który może wywołać wyjątek
except:
    # Kod wykonywany w przypadku wystąpienia wyjątku
finally:
    # Kod wykonywany zawsze, niezależnie od wystąpienia wyjątku

Konstrukcja składa się z trzech kluczowych słów:

`try`

Słowo kluczowe `try` rozpoczyna blok kodu, który potencjalnie może wywołać wyjątek. Interpreter Pythona próbuje wykonać kod w tym bloku. Jeśli w trakcie wykonywania kodu zostanie zgłoszony wyjątek, program natychmiast przerywa wykonywanie bloku `try` i przechodzi do wykonania kodu w bloku `except`.

`except`

Słowo kluczowe `except` rozpoczyna blok kodu, który zostanie wykonany, jeśli w bloku `try` wystąpi wyjątek. Możemy zdefiniować kilka bloków `except`, każdy dla innego typu wyjątku. Zostanie to omówione w dalszej części artykułu.

`finally`

Słowo kluczowe `finally` wprowadza blok kodu, który zostanie wykonany zawsze, niezależnie od tego, czy w bloku `try` wystąpi wyjątek, czy nie.

Przykład

Poniższy przykład pokazuje, jak za pomocą tych słów kluczowych można obsłużyć wyjątek. Zmodyfikujemy w tym celu wcześniejszy przykład:

try:
    user_input = input("Wprowadź liczbę: ")
    num = int(user_input)
    print("Twoja liczba podwojona to:", num * 2)
except:
    print("Wystąpił błąd")
finally:
    print("Ten kod zostanie wykonany zawsze")

Jeśli uruchomisz powyższy kod wprowadzając liczbę 5, uzyskasz następujący wynik:

Natomiast jeśli wprowadzisz słowo „cześć”, otrzymasz następujący rezultat:

Jak widzimy, jeżeli w bloku `try` nie wystąpił wyjątek, program przechodzi bezpośrednio do bloku `finally`. Jeżeli natomiast w bloku `try` wystąpił wyjątek, program wykonuje blok `except`, a następnie `finally`.

Możemy również obsługiwać konkretne typy wyjątków. Na przykład, jeśli chcemy inaczej obsłużyć wyjątek `ValueError` a inaczej `KeyboardInterrupt`, możemy zmodyfikować kod w następujący sposób:

try:
    user_input = input("Wprowadź liczbę: ")
    num = int(user_input)
    print("Twoja liczba podwojona to:", num * 2)
except ValueError:
    print("Wartość nie może zostać przekonwertowana na liczbę całkowitą")
except KeyboardInterrupt:
    print("Odebrano sygnał przerwania z klawiatury")
except:
    print("Ogólny blok obsługi wyjątków")
finally:
    print("Ten kod zostanie wykonany zawsze")

W powyższym przykładzie mamy trzy bloki `except`. Pierwszy blok obsługuje tylko wyjątki typu `ValueError`, drugi tylko `KeyboardInterrupt`. Ostatni blok `except` bez określonego typu wyjątku, przechwytuje wszystkie pozostałe wyjątki.

Po uruchomieniu powyższego kodu, otrzymamy wyniki zbliżone do tych:

W przypadku wystąpienia wyjątku, można uzyskać dodatkowe informacje o nim, korzystając z obiektu wyjątku. Aby uzyskać dostęp do tego obiektu, używamy słowa kluczowego `as`:

try:
    user_input = input("Wprowadź liczbę: ")
    num = int(user_input)
    print("Twoja liczba podwojona to:", num * 2)
except ValueError as e:
    print("Błąd wartości:", e)
except KeyboardInterrupt as e:
    print("Przerwanie z klawiatury:", e)
except Exception as e:
    print("Inny wyjątek:", e)

Jak wywoływać wyjątki

Do tej pory zajmowaliśmy się wyjątkami wywoływanymi przez inne funkcje. Możliwe jest również samodzielne wywołanie wyjątku w naszym kodzie. Używamy do tego słowa kluczowego `raise`. Określamy również klasę reprezentującą typ wyjątku, który chcemy wywołać oraz komunikat zrozumiały dla człowieka.

W poniższym przykładzie, wykorzystujemy ogólną klasę wyjątku, aby wywołać wyjątek. Następnie, przekazujemy komunikat do konstruktora tej klasy.

raise Exception('Wystąpił błąd')

Po uruchomieniu tego fragmentu kodu, otrzymamy taki wynik:

Możemy też wywoływać różne, bardziej konkretne typy wyjątków. Na przykład, możemy wywołać wyjątek `TypeError`, jeżeli wartość ma nieprawidłowy typ:

def double(x):
    if isinstance(x, int):
        return x * 2
    else:
        raise TypeError('x musi być liczbą całkowitą')

Lub wyjątek `ValueError`, jeżeli wartość jest poza akceptowalnym zakresem:

def say_hello(name):
    if name == '':
        raise ValueError('Wartość poza zakresem')
    else:
        print('Witaj', name)

Możemy również tworzyć własne typy wyjątków, dziedzicząc po klasie `Exception`. Oto przykład:

class InvalidHTTPMethod(Exception):
    pass

W powyższym przykładzie stworzyliśmy klasę `InvalidHTTPMethod`, która dziedziczy po klasie `Exception`. Możemy jej użyć w taki sam sposób, jak wcześniej, do wywołania wyjątku:

raise InvalidHTTPMethod('Metoda musi być GET lub POST')

Typowe zastosowania obsługi wyjątków

Obsługa wyjątków znajduje zastosowanie w wielu różnych scenariuszach. Wcześniejszy przykład pokazywał, jak można obsłużyć wyjątki związane z danymi wprowadzonymi przez użytkownika. W tej sekcji omówimy dwa kolejne przypadki, w których obsługa wyjątków jest szczególnie przydatna: obsługę wyjątków podczas wykonywania zapytań sieciowych oraz obsługę wyjątków przy odczycie plików.

Wysyłanie zapytań sieciowych

W poniższym przykładzie wysyłamy zapytanie do serwera Google. Wykorzystujemy obsługę wyjątków, aby poradzić sobie z ewentualnymi problemami. Wyjątki te są zdefiniowane w module `requests.exceptions`.

import requests

try:
    response = requests.get("https://google.com")

    # Sprawdź, czy kod statusu odpowiedzi jest w zakresie 200-299 (pomyślna odpowiedź)
    if 200 <= response.status_code < 300:
        print("Zapytanie zakończone sukcesem!")
    else:
        print(f"Zapytanie nie powiodło się, kod statusu: {response.status_code}")
except requests.exceptions.RequestException as e:
    print(f"Wystąpił wyjątek RequestException: {e}")
except requests.exceptions.ConnectionError as e:
    print(f"Wystąpił wyjątek ConnectionError: {e}")
except requests.exceptions.Timeout as e:
    print(f"Wystąpił wyjątek Timeout: {e}")
except requests.exceptions.TooManyRedirects as e:
    print(f"Wystąpił wyjątek TooManyRedirects: {e}")
except requests.exceptions.HTTPError as e:
    print(f"Wystąpił wyjątek HTTPError: {e}")
except Exception as e:
    print(f"Wystąpił nieoczekiwany błąd: {e}")

Odczyt danych z pliku

W tym przykładzie odczytujemy dane z pliku o nazwie `hello.txt`. Obsługujemy typowe wyjątki, które mogą wystąpić podczas tej operacji, takie jak `FileNotFoundError` i `IOError`.

try:
    with open(file_path, 'r') as file:
        data = file.read()
        print("Zawartość pliku:")
        print(data)
except FileNotFoundError as e:
    print(f"Wystąpił wyjątek FileNotFoundError: {e}")
except IOError as e:
    print(f"Wystąpił wyjątek IOError: {e}")
except Exception as e:
    print(f"Wystąpił nieoczekiwany błąd: {e}")

Podsumowanie

W tym artykule wyjaśniliśmy, czym są wyjątki i dlaczego są zgłaszane. Dowiedzieliśmy się również, że obsługa wyjątków jest niezbędna, aby kod był bardziej niezawodny i nie ulegał nagłym awariom. Omówiliśmy, jak obsługiwać wyjątki, a także jak samodzielnie je wywoływać.

Zachęcamy do zapoznania się z typowymi błędami w Pythonie i sposobami ich rozwiązywania.


newsblog.pl