1. Какво е изключение?

Изключение е грешка, която възниква по време на изпълнение на програмата. Изключения могат да възникнат по много причини, включително:

  • Неправилно въведено от потребителя
  • Проблеми с достъпа до външни ресурси (напр. файлове, бази данни, мрежа)
  • Грешки в кода
  • Неочаквани условия (напр. липса на памет, хардуерен срив)

Когато възникне изключение, то прекъсва нормалния поток на изпълнение на програмата и може да доведе до срив на програмата. Ето защо е важно да обработвате изключения във вашия код на Python, за да сте сигурни, че вашата програма работи гладко и без неочаквани грешки.

2. Блокът try-except

Блокът try-except се използва за улавяне и обработка на изключения, които възникват по време на изпълнение на програмата. Синтаксисът на блока try-except е както следва:

try:
    # code that may raise an exception
except ExceptionType as e:
    # code to handle the exception

В този код блокът try съдържа кода, който може да предизвика изключение. Ако възникне изключение, Python търси подходящ блок за изключение, за да обработи изключението. Ако бъде намерен блок except за подходящия тип изключение, кодът в този блок се изпълнява.

Например, да приемем, че имате функция, която чете файл и връща съдържанието му:

def read_file(filename):
    try:
        with open(filename, 'r') as f:
            return f.read()
    except FileNotFoundError:
        print(f"Error: file {filename} not found")

В този пример функцията read_file използва блока try-except, за да улови грешката FileNotFoundError, която може да възникне, ако посоченият файл не съществува. Ако възникне изключение, функцията отпечатва съобщение за грешка.

3. Обработка на множество изключения

Можете също така да обработвате множество типове изключения в един и същ блок try-except, като включите множество блокове с изключение. Синтаксисът за обработка на множество изключения е както следва:

try:
    # code that may raise an exception
except ExceptionType1:
    # code to handle ExceptionType1
except ExceptionType2:
    # code to handle ExceptionType2
...
except ExceptionTypeN:
    # code to handle ExceptionTypeN

Например, да кажем, че имате функция, която разделя две числа:

def divide(x, y):
    try:
        return x / y
    except ZeroDivisionError:
        print("Error: cannot divide by zero")
    except TypeError:
        print("Error: inputs must be numbers")

В този пример функцията divide използва блока try-except, за да улови както ZeroDivisionError, която може да възникне, ако вторият вход е нула, така и TypeError, която може да възникне, ако някое от въведените данни не е число.

4. Блокът else

Можете също така да включите блок else в блок try-except. Кодът в блока else се изпълнява, ако не възникнат изключения в блока try. Синтаксисът за включване на блок else е както следва:

try:
    # code that may raise an exception
except ExceptionType:
    # code to handle the exception
else:
    # code to execute if no exception occurs

Например, да кажем, че имате функция, която чете файл и връща съдържанието му, и искате да отпечатате съобщение, ако файлът е прочетен успешно:

def read_file(filename):
    try:
        with open(filename, 'r') as f:
            contents = f.read()
    except FileNotFoundError:
        print(f"Error: file {filename} not found")
    else:
        print(f"File {filename} read successfully")
        return contents

В този пример функцията read_file използва блока try-except-else, за да улови грешката FileNotFoundError, която може да възникне, ако посоченият файл не съществува и да отпечатате съобщение, ако файлът е прочетен успешно.

5. Окончателният блок

Можете също да включите блок finally в блок try-except. Кодът в блока finally винаги се изпълнява, независимо дали възниква изключение в блока try или не. Синтаксисът за включване на блок finally е както следва:

try:
    # code that may raise an exception
except ExceptionType:
    # code to handle the exception
finally:
    # code to execute regardless of whether an exception occurs

Например, да приемем, че имате функция, която се свързва с база данни и връща резултатите от заявка:

import sqlite3

def query_database(query):
    try:
        conn = sqlite3.connect('mydatabase.db')
        cursor = conn.cursor()
        cursor.execute(query)
        results = cursor.fetchall()
        return results
    except sqlite3.Error:
        print("Error: database query failed")
    finally:
        conn.close()

В този пример функцията query_database използва блока try-except-finally, за да улови sqlite3.Error, която може да възникне, ако заявката е неуспешна, и да се гарантира, че връзката с базата данни е затворена, независимо дали възникне изключение.

6. Ръчно повдигане на изключения

В допълнение към прихващането на изключения, можете също да повдигате изключения ръчно, като използвате израза за повишаване. Синтаксисът за ръчно повдигане на изключение е следният:

raise ExceptionType("error message")

Например, да приемем, че имате функция, която проверява дали дадено число е положително и предизвиква изключение, ако не е:

def check_positive(n):
    if n <= 0:
        raise ValueError("number must be positive")
    return n

В този пример функцията check_positive повдига ValueError със съобщението „числото трябва да е положително“ако въведеното не е положително.

7. Най-добри практики за обработка на изключения

Ето някои най-добри практики, които трябва да имате предвид, когато обработвате изключения във вашия код на Python:

  • Улавяйте само изключенията, с които можете да се справите: Улавянето на твърде много изключения може да направи кода ви по-труден за отстраняване на грешки и поддръжка. Прихващайте само изключения, с които знаете как да се справите, и оставете другите да се разпространяват нагоре в стека на повикванията.
  • Бъдете конкретни, когато улавяте изключения: Хващането на общ тип изключение може да маскира грешките и да направи кода ви по-малко надежден. Хващайте само специфичните типове изключения, с които знаете как да се справите.
  • Пазете обработката на изключения отделно от бизнес логиката: Избягвайте да смесвате обработката на изключения с вашата бизнес логика. Вместо това обработвайте изключенията в отделен слой на вашия код.
  • Регистриране на изключения: Регистрирането на изключения може да ви помогне да отстраните грешки в кода си и да идентифицирате често срещани режими на неизправност. Използвайте библиотека за регистриране като logging, за да регистрирате изключения във вашия код.

8. Заключение

В този блог разгледахме основите на обработката на изключения в Python, включително как да улавяте и обработвате изключения, как да създавате изключения ръчно и най-добрите практики за обработка на грешки във вашия код на Python. Като следвате тези най-добри практики, можете да пишете по-стабилен и надежден код на Python, който е по-малко податлив на неочаквани грешки и сривове.