Как проверить, вызывает ли функция исключение в Python

PythonPythonBeginner
Практиковаться сейчас

💡 Этот учебник переведен с английского с помощью ИИ. Чтобы просмотреть оригинал, вы можете перейти на английский оригинал

Введение

В этом практическом занятии (лабораторной работе) вы научитесь проверять, вызывает ли функция исключение в Python. Практическое занятие начинается с изучения исключений и того, как они могут возникать в функциях. Вы создадите простую функцию на Python, которая может вызвать исключение ZeroDivisionError, и посмотрите на трассировку стека при возникновении этого исключения.

Затем вы реализуете блок try-except для корректной обработки исключения. Наконец, вы научитесь использовать pytest.raises для проверки, вызывает ли функция определенное исключение (необязательное введение).


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL python(("Python")) -.-> python/ErrorandExceptionHandlingGroup(["Error and Exception Handling"]) python/ErrorandExceptionHandlingGroup -.-> python/catching_exceptions("Catching Exceptions") python/ErrorandExceptionHandlingGroup -.-> python/raising_exceptions("Raising Exceptions") subgraph Lab Skills python/catching_exceptions -.-> lab-559520{{"Как проверить, вызывает ли функция исключение в Python"}} python/raising_exceptions -.-> lab-559520{{"Как проверить, вызывает ли функция исключение в Python"}} end

Исследование исключений в функциях

На этом этапе вы узнаете о исключениях и о том, как они могут возникать в функциях на Python. Понимание исключений является важным аспектом при написании надежного и устойчивого к ошибкам кода. Исключения - это события, которые прерывают нормальный поток выполнения программы. Они могут возникать по различным причинам, например, из-за некорректного ввода, отсутствия файла или сетевых ошибок.

Начнем с создания простой функции на Python, которая может вызвать исключение. Откройте редактор VS Code в среде LabEx и создайте новый файл с именем exceptions_example.py в директории ~/project.

## ~/project/exceptions_example.py
def divide(x, y):
    return x / y

print(divide(10, 2))
print(divide(5, 0))

В этом коде:

  • Мы определяем функцию divide, которая принимает два аргумента, x и y, и возвращает результат деления x на y.
  • Сначала мы вызываем функцию divide с аргументами 10 и 2, в результате чего на консоль будет выведено значение 5.0.
  • Затем мы вызываем функцию divide с аргументами 5 и 0. Это вызовет исключение ZeroDivisionError, так как деление на ноль запрещено.

Теперь запустим этот скрипт. Откройте терминал в VS Code (его можно найти в меню "View" -> "Terminal") и выполните следующую команду:

python ~/project/exceptions_example.py

Вы увидите вывод, похожий на следующий:

5.0
Traceback (most recent call last):
  File "/home/labex/project/exceptions_example.py", line 4, in <module>
    print(divide(5, 0))
  File "/home/labex/project/exceptions_example.py", line 2, in divide
    return x / y
ZeroDivisionError: division by zero

Как вы можете видеть, первая инструкция print была успешно выполнена, и на консоль был выведен результат 5.0. Однако, когда функция divide была вызвана с y = 0, возникло исключение ZeroDivisionError, и программа завершилась. Трассировка стека показывает последовательность вызовов функций, которая привела к возникновению исключения, что может быть полезно для отладки.

Этот пример демонстрирует, как исключения могут возникать в функциях и как они могут прерывать нормальный поток выполнения программы. На следующем этапе вы научитесь обрабатывать исключения с помощью блоков try и except.

Реализация блока try-except

На предыдущем этапе вы увидели, как исключения могут привести к внезапному завершению программы. Чтобы корректно обрабатывать исключения и избежать аварийного завершения программы, можно использовать блоки try и except.

Блок try позволяет заключить в себя участок кода, в котором может возникнуть исключение. Если исключение возникает внутри блока try, программа переходит в соответствующий блок except, где можно обработать это исключение.

Давайте модифицируем файл exceptions_example.py, добавив в него блок try-except для обработки исключения ZeroDivisionError. Откройте файл exceptions_example.py в редакторе VS Code и измените его следующим образом:

## ~/project/exceptions_example.py
def divide(x, y):
    try:
        result = x / y
        return result
    except ZeroDivisionError:
        return "Cannot divide by zero!"

print(divide(10, 2))
print(divide(5, 0))
print(divide(8, 4))

В этом модифицированном коде:

  • Мы добавили блок try вокруг операции x / y. Это означает, что если при выполнении деления возникнет исключение ZeroDivisionError, программа перейдёт в блок except.
  • Строка except ZeroDivisionError: указывает, что мы хотим обработать исключения типа ZeroDivisionError.
  • Внутри блока except мы возвращаем строку "Cannot divide by zero!". Эта строка будет выведена на консоль вместо аварийного завершения программы.

Теперь запустим модифицированный скрипт. Откройте терминал в VS Code и выполните следующую команду:

python ~/project/exceptions_example.py

Вы увидите вывод, похожий на следующий:

5.0
Cannot divide by zero!
2.0

Как вы можете видеть, программа больше не завершается аварийно при делении на ноль. Вместо этого блок except перехватывает исключение ZeroDivisionError, и выводится сообщение "Cannot divide by zero!". Затем программа продолжает выполнение, и последняя инструкция print также выполняется успешно.

Блоки try-except также можно использовать для обработки других типов исключений. Например, можно использовать блок try-except для обработки исключений TypeError, которые могут возникнуть при попытке выполнить операцию над нессовместимыми типами данных. Также можно использовать несколько блоков except для обработки разных типов исключений.

На следующем этапе вы узнаете, как использовать pytest для проверки на возникновение исключений.

Тестирование с использованием pytest.raises (Необязательное введение)

На этом необязательном этапе вы получите краткое введение в использование pytest для тестирования на возникновение исключений. pytest - это популярный фреймворк для тестирования на Python, который упрощает процесс написания и запуска тестов.

Сначала установим pytest. Откройте терминал в VS Code и выполните следующую команду:

pip install pytest

Эта команда загрузит и установит pytest и его зависимости.

Теперь создадим файл с тестами для нашей функции divide. Создайте новый файл с именем test_exceptions.py в директории ~/project.

## ~/project/test_exceptions.py
import pytest
from exceptions_example import divide

def test_divide_by_zero():
    with pytest.raises(ZeroDivisionError):
        divide(5, 0)

def test_divide_valid():
    assert divide(10, 2) == 5

В этом коде:

  • Мы импортируем модуль pytest и функцию divide из файла exceptions_example.py.
  • Мы определяем тестовую функцию test_divide_by_zero. Эта функция использует pytest.raises для проверки того, что вызов divide(5, 0) вызовет исключение ZeroDivisionError. Блок with pytest.raises(ZeroDivisionError): гарантирует, что тест пройдет успешно только в том случае, если внутри блока возникнет исключение ZeroDivisionError.
  • Мы определяем еще одну тестовую функцию test_divide_valid. Эта функция проверяет, что вызов divide(10, 2) возвращает значение 5.

Для запуска тестов откройте терминал в VS Code и выполните следующую команду:

pytest ~/project/test_exceptions.py

Вы должны увидеть вывод, похожий на следующий:

============================= test session starts ==============================
platform linux -- Python 3.10.12, pytest-7.4.4, pluggy-1.3.0
rootdir: /home/labex/project
collected 2 items

test_exceptions.py ..                                                      [100%]

============================== 2 passed in 0.01s ===============================

Вывод показывает, что было собрано два теста и что оба теста прошли успешно. Это означает, что наша функция divide работает как ожидается: она вызывает исключение ZeroDivisionError при делении на ноль и возвращает правильный результат при делении на ненулевое число.

Это очень простой пример использования pytest для тестирования на возникновение исключений. pytest имеет множество других возможностей, которые помогут вам написать более полноценные и эффективные тесты.

Резюме

В этом практическом занятии вы начали с изучения исключений в функциях Python, понимая, что исключения - это события, которые нарушают нормальный поток выполнения программы. Вы создали функцию divide, которая вызывает исключение ZeroDivisionError при делении на ноль. При запуске скрипта показано, как исключение завершает программу и предоставляет трассировку стека для отладки.

В практическом занятии подчеркивается важность понимания исключений для написания надежного кода, демонстрируется простой пример функции, которая может вызвать исключение, и показано, как наблюдать возникающую ошибку и трассировку стека при возникновении исключения.