неопределенная ошибка не вызывает ошибку имени, и программа работает

Вопрос или проблема

Почему мой код здесь не вызывает NameError или SyntaxError, когда я явно использую несуществующее имя ошибки?

def fun(x):
    assert x >= 0
    return x ** 0.5

def mid_level(x):
    try:
        fun(x)
    except ButtError: 
        print(333)
        raise
    print(444)

try:
    x = mid_level(-1)
except RuntimeError:
    x = -1
except Exception:
    x = 9
except:
    x = -2

print(x)

Ответ или решение

Когда вы сталкиваетесь с кодом, который не вызывает ошибки NameError или SyntaxError, несмотря на использование несуществующего имени ошибки, необходимо рассмотреть несколько ключевых моментов, касающихся обработки исключений в Python.

Рассмотрение вашего кода

В вашем коде определены две функции: fun и mid_level. Основные моменты, на которые стоит обратить внимание:

  1. Функция fun:

    • Эта функция принимает значение x и проверяет, что x неотрицательное, используя оператор assert. Если x меньше нуля, будет выброшено исключение AssertionError.
  2. Функция mid_level:

    • Внутри функции mid_level вызывается функция fun(x). В случае, если fun(x) вызывает исключение, обработчик исключений try-except должен отловить его.
    • Однако вы используете except ButtError, что является несуществующим типом ошибки (если у вас не определен пользовательский класс исключения с таким именем).
  3. Основной блок обработки исключений:

    • Также присутствует блок обработки исключений, в котором разные типы ошибок обрабатываются по-разному.

Почему программа выполняется без ошибок

Теперь давайте разберемся, почему ваше приложение не вызывает NameError или SyntaxError и вместо этого выполняется корректно:

  • Неисключительная ошибка: В Python, если исключение не перехватывается в блоке try, оно поднимается дальше в стек вызовов. В вашем случае, функция fun вызывает AssertionError, а не ButtError, который вы указали в except. Поэтому, как только AssertionError возникает в функции fun, контроль передается на следующее подходящее исключение, что не совпадает с ButtError.

  • Обработка RuntimeError или Exception: После того как происходит AssertionError, управление передается в блок try верхнего уровня, где первый подходящий обработчик — это except RuntimeError. Но AssertionError не является производным от RuntimeError, поэтому будет обрабатываться следующий except Exception. Итак, поскольку Exception является базовым классом для всех стандартных исключений, этот блок перехватит AssertionError и установит переменную x равной 9.

  • Последний else блок: Ваш код также содержит блок except, который используется в качестве универсального перехватчика, но он не будет достигнут, поскольку мы справились с ошибкой на предыдущих этапах.

Заключение

Таким образом, хотя у вас есть несуществующий класс ошибки (ButtError), это не вызывает NameError, поскольку Python сначала выполняет код и только после этого обрабатывает исключения. В вашем случае программа завершилась, присвоив переменной x значение 9, в результате успешной обработки AssertionError в блоке except Exception.

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

Оцените материал
Добавить комментарий

Капча загружается...