Как проверить, было ли поймано исключение в Python

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

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

Введение

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

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


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL python(("Python")) -.-> python/ErrorandExceptionHandlingGroup(["Error and Exception Handling"]) python(("Python")) -.-> python/FileHandlingGroup(["File Handling"]) python(("Python")) -.-> python/AdvancedTopicsGroup(["Advanced Topics"]) python(("Python")) -.-> python/ControlFlowGroup(["Control Flow"]) python/ControlFlowGroup -.-> python/conditional_statements("Conditional Statements") python/ErrorandExceptionHandlingGroup -.-> python/catching_exceptions("Catching Exceptions") python/ErrorandExceptionHandlingGroup -.-> python/raising_exceptions("Raising Exceptions") python/FileHandlingGroup -.-> python/file_opening_closing("Opening and Closing Files") python/FileHandlingGroup -.-> python/file_operations("File Operations") python/AdvancedTopicsGroup -.-> python/context_managers("Context Managers") subgraph Lab Skills python/conditional_statements -.-> lab-559610{{"Как проверить, было ли поймано исключение в Python"}} python/catching_exceptions -.-> lab-559610{{"Как проверить, было ли поймано исключение в Python"}} python/raising_exceptions -.-> lab-559610{{"Как проверить, было ли поймано исключение в Python"}} python/file_opening_closing -.-> lab-559610{{"Как проверить, было ли поймано исключение в Python"}} python/file_operations -.-> lab-559610{{"Как проверить, было ли поймано исключение в Python"}} python/context_managers -.-> lab-559610{{"Как проверить, было ли поймано исключение в Python"}} end

Изучение процесса обработки исключений

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

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

  1. Откройте редактор VS Code в среде LabEx.

  2. Создайте новый файл с именем division.py в каталоге ~/project.

    touch ~/project/division.py
  3. Отредактируйте файл division.py и добавьте следующий код:

    ## division.py
    numerator = 10
    denominator = 0
    
    result = numerator / denominator
    
    print(result)
  4. Запустите скрипт с помощью команды python:

    python ~/project/division.py

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

Traceback (most recent call last):
  File "/home/labex/project/division.py", line 4, in <module>
    result = numerator / denominator
ZeroDivisionError: division by zero

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

Теперь используем обработку исключений для элегантной обработки этой ошибки.

  1. Измените файл division.py, добавив блок try...except:

    ## division.py
    numerator = 10
    denominator = 0
    
    try:
        result = numerator / denominator
        print(result)
    except ZeroDivisionError:
        print("Error: Cannot divide by zero.")

В этом коде блок try содержит код, который может вызвать исключение. Если в блоке try возникает исключение ZeroDivisionError, будет выполнен код в блоке except.

  1. Запустите скрипт еще раз:

    python ~/project/division.py

Теперь вместо аварийного завершения программа выведет:

Error: Cannot divide by zero.

Это демонстрирует базовую структуру обработки исключений:

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

Вы также можете ловить несколько типов исключений с помощью нескольких блоков except:

## division.py
numerator = 10
denominator = "abc"

try:
    result = numerator / int(denominator)
    print(result)
except ZeroDivisionError:
    print("Error: Cannot divide by zero.")
except ValueError:
    print("Error: Invalid input. Please enter a number.")

В этом примере мы добавили обработчик исключения ValueError. Если denominator не может быть преобразован в целое число (например, если это строка, такая как "abc"), будет вызвано исключение ValueError, и будет выполнен соответствующий блок except.

Запустите скрипт:

python ~/project/division.py

Вывод:

Error: Invalid input. Please enter a number.

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

Установка флага в блоке except

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

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

  1. Откройте редактор VS Code в среде LabEx.

  2. Измените файл division.py в каталоге ~/project, добавив флаг:

    ## division.py
    numerator = 10
    denominator = 2
    success = True  ## Initialize the flag to True
    
    try:
        result = numerator / denominator
        print("Result of division:", result)
    except ZeroDivisionError:
        print("Error: Cannot divide by zero.")
        success = False  ## Set the flag to False if an error occurs
    except ValueError:
        print("Error: Invalid input. Please enter a number.")
        success = False ## Set the flag to False if an error occurs
    else:
        print("No exception occurred.")
    
    if success:
        try:
            reciprocal = 1 / result
            print("Reciprocal:", reciprocal)
        except ZeroDivisionError:
            print("Cannot calculate reciprocal of zero.")
    else:
        print("Reciprocal calculation skipped due to error.")

    В этом коде:

    • Мы инициализируем флаг с именем success со значением True перед блоком try.
    • Если возникает исключение ZeroDivisionError или ValueError, мы устанавливаем флаг success в значение False внутри соответствующего блока except.
    • После блока try...except мы проверяем значение флага success. Если оно по-прежнему равно True, это означает, что исключение не произошло, и мы можем безопасно вычислить обратное число. В противном случае мы пропускаем вычисление обратного числа.
    • Мы также добавили блок else, который будет выполнен, если в блоке try не произошло никаких исключений.
  3. Запустите скрипт с допустимым значением знаменателя:

    python ~/project/division.py

    Вывод:

    Result of division: 5.0
    No exception occurred.
    Reciprocal: 0.2
  4. Теперь измените значение denominator на 0 и запустите скрипт снова:

    ## division.py
    numerator = 10
    denominator = 0 ## Change the denominator to 0
    success = True
    
    try:
        result = numerator / denominator
        print("Result of division:", result)
    except ZeroDivisionError:
        print("Error: Cannot divide by zero.")
        success = False
    except ValueError:
        print("Error: Invalid input. Please enter a number.")
        success = False
    else:
        print("No exception occurred.")
    
    if success:
        try:
            reciprocal = 1 / result
            print("Reciprocal:", reciprocal)
        except ZeroDivisionError:
            print("Cannot calculate reciprocal of zero.")
    else:
        print("Reciprocal calculation skipped due to error.")

    Запустите скрипт:

    python ~/project/division.py

    Вывод:

    Error: Cannot divide by zero.
    Reciprocal calculation skipped due to error.

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

Использование менеджеров контекста для управления

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

Менеджер контекста - это объект, который определяет методы __enter__ и __exit__. Оператор with используется для выполнения блока кода в контексте менеджера контекста. Метод __enter__ вызывается при входе в блок with, а метод __exit__ - при выходе из блока with, независимо от того, произошло ли исключение.

Начнем с простого примера чтения файла с использованием менеджера контекста.

  1. Откройте редактор VS Code в среде LabEx.

  2. Создайте новый файл с именем file_handling.py в каталоге ~/project.

    touch ~/project/file_handling.py
  3. Отредактируйте файл file_handling.py и добавьте следующий код:

    ## file_handling.py
    
    filename = "my_file.txt"
    
    try:
        with open(filename, "w") as f:
            f.write("Hello, LabEx!\n")
            f.write("This is a test file.\n")
    except IOError as e:
        print(f"An I/O error occurred: {e}")
    
    try:
        with open(filename, "r") as f:
            content = f.read()
            print("File content:")
            print(content)
    except FileNotFoundError:
        print(f"The file '{filename}' was not found.")
    except IOError as e:
        print(f"An I/O error occurred: {e}")

    В этом коде:

    • Мы используем оператор with open(filename, "w") as f:, чтобы открыть файл my_file.txt в режиме записи ("w"). Функция open() возвращает объект файла, который присваивается переменной f.
    • Оператор with гарантирует, что файл автоматически закроется при выходе из блока, даже если возникнет исключение.
    • Мы записываем две строки текста в файл с помощью метода f.write().
    • Затем мы используем оператор with open(filename, "r") as f:, чтобы открыть тот же файл в режиме чтения ("r").
    • Мы читаем весь контент файла с помощью метода f.read() и выводим его в консоль.
    • Мы оборачиваем операции с файлом в блоки try...except, чтобы обработать потенциальные исключения FileNotFoundError и IOError.
  4. Запустите скрипт:

    python ~/project/file_handling.py

    Вывод:

    File content:
    Hello, LabEx!
    This is a test file.

    Если файл my_file.txt не существует, скрипт создаст его и запишет указанный контент. Если файл уже существует, его содержимое будет перезаписано. Оператор with гарантирует, что файл будет правильно закрыт в любом случае.

Рассмотрим другой пример, где исключение может возникнуть во время обработки файла:

## file_handling.py
filename = "my_file.txt"

try:
    with open(filename, "r") as f:
        for line in f:
            ## Simulate an error during processing
            if "test" in line:
                raise ValueError("Simulated error during processing")
            print("Line:", line.strip())
except FileNotFoundError:
    print(f"The file '{filename}' was not found.")
except ValueError as e:
    print(f"A value error occurred: {e}")
except IOError as e:
    print(f"An I/O error occurred: {e}")

В этом примере мы имитируем ошибку, вызывая исключение ValueError, если строка содержит слово "test". Даже если эта ошибка произойдет, оператор with гарантирует, что файл будет правильно закрыт.

Запустите скрипт:

python ~/project/file_handling.py

Вывод:

Line: Hello, LabEx!
A value error occurred: Simulated error during processing

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

Резюме

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