Вопрос или проблема
Почему мой код здесь не вызывает 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
. Основные моменты, на которые стоит обратить внимание:
-
Функция
fun
:- Эта функция принимает значение
x
и проверяет, чтоx
неотрицательное, используя операторassert
. Еслиx
меньше нуля, будет выброшено исключениеAssertionError
.
- Эта функция принимает значение
-
Функция
mid_level
:- Внутри функции
mid_level
вызывается функцияfun(x)
. В случае, еслиfun(x)
вызывает исключение, обработчик исключенийtry-except
должен отловить его. - Однако вы используете
except ButtError
, что является несуществующим типом ошибки (если у вас не определен пользовательский класс исключения с таким именем).
- Внутри функции
-
Основной блок обработки исключений:
- Также присутствует блок обработки исключений, в котором разные типы ошибок обрабатываются по-разному.
Почему программа выполняется без ошибок
Теперь давайте разберемся, почему ваше приложение не вызывает 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
.
Рекомендуется использовать существующие классы исключений и, если необходимо, определить свои собственные классы, расположив их на соответствующем уровне иерархии исключений. Это позволит предотвратить путаницу и улучшить диагностику ошибок в вашем коде.