Любой код, который вызывает исключение, делал это явно, включая KeyError
.Никакой специальной обработки не требуется для пользовательских исключений по сравнению со встроенными типами.try...except
может перехватить исключение, только если оно было вызвано кодом, выполненным любым оператором внутри try
.Это включает в себя любые дальнейшие вызовы функций, цепочку вызовов вместе в стек вызовов.
В следующем примере
>>> d = {}
>>> d['foo']
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 'foo'
KeyError
не возникает из ничего, реализация Python dict
явно вызывает это исключение.Это не всегда может быть очевидным, потому что собственный код (код, реализованный здесь на C) не отображается в трассировке Python.
Для операции подписки d[...]
функция dict_subscript()
вызывает _PyErr_SetKeyError(key);
, вспомогательную функцию, которая использует PyErr_SetObject()
, эквивалент C * raise
, чтобы вызвать исключение KeyError(key)
.
Работает отлов исключенийто же самое для всех типов исключений, пользовательские исключения здесь не являются особенными.Когда возникает исключение, нормальный поток кода прерывается, и стек вызовов отменяется до тех пор, пока не встретится активный оператор try
, а затем все обработчики исключений проверяются в порядке определения в исходном коде с помощью isinstance(active_exception, ExceptionClassBeingHandled)
.
Если ничто не перехватывает исключение, Python продолжает раскручивать стек вызовов, пока не достигнет последнего кадра стека, после чего Python завершит трассировку стека, если ничего не перехватит исключение.