← Назад к вопросам

Где может находиться исключение в Python?

2.0 Middle🔥 81 комментариев
#Python Core

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Где может находиться исключение в Python?

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

Основная позиция: sys.exc_info()

Текущее исключение, которое обрабатывается, доступно через встроенный модуль sys:

import sys

try:
    1 / 0
except ZeroDivisionError:
    exc_type, exc_value, exc_traceback = sys.exc_info()
    print(exc_type)        # <class ZeroDivisionError>
    print(exc_value)       # division by zero
    print(exc_traceback)   # traceback object

Можно использовать sys.exc_info() только в блоке except или при обработке исключения. После выхода из блока it вернёт (None, None, None).

В цепочке исключений

При возбуждении нового исключения внутри except блока, Python сохраняет оригинальное исключение в цепочку:

try:
    try:
        1 / 0
    except ZeroDivisionError as e:
        raise ValueError("Invalid operation") from e
except ValueError as e:
    print(f"Exception: {e}")
    print(f"Caused by: {e.__cause__}")  # Оригинальное исключение

Атрибуты цепочки исключений:

  • __cause__ — явно указанное исключение (from e)
  • __context__ — неявно подавленное исключение (при raise внутри except)
  • __suppress_context__ — флаг, должно ли показываться context

В переменной исключения

try:
    risky_operation()
except ValueError as e:
    # Исключение находится в переменной e
    print(e)           # сообщение
    print(type(e))     # тип
    print(e.args)      # аргументы конструктора
    print(e.__traceback__)  # объект traceback

В контексте функции

Если исключение не было перехвачено в функции, оно распространяется вверх по стеку вызовов:

def level_3():
    raise RuntimeError("Something went wrong")

def level_2():
    level_3()  # Исключение поднимается выше

def level_1():
    try:
        level_2()
    except RuntimeError as e:
        # Исключение обработано здесь
        print(f"Caught in level_1: {e}")

В контексте контекстного менеджера

В методе __exit__ контекстного менеджера исключение доступно через аргументы:

class MyContext:
    def __enter__(self):
        return self
    
    def __exit__(self, exc_type, exc_value, exc_traceback):
        if exc_type is not None:
            print(f"Exception occurred: {exc_type.__name__}")
            print(f"Value: {exc_value}")
            print(f"Traceback: {exc_traceback}")
            return False  # Не подавлять исключение
        return True

with MyContext():
    1 / 0  # Исключение будет передано в __exit__

В последних обработчиках (finally)

try:
    1 / 0
except ZeroDivisionError as e:
    print(f"Handling: {e}")
finally:
    # В finally нельзя получить исключение через except
    # Но его всё ещё можно получить через sys.exc_info()
    import sys
    if sys.exc_info()[0] is not None:
        print("Exception was raised")

В обработчиках сигналов

В signal handlers исключение может быть недоступно обычным способом:

import signal

def signal_handler(signum, frame):
    # Здесь нет текущего исключения
    raise KeyboardInterrupt("Caught SIGINT")

signal.signal(signal.SIGINT, signal_handler)

В асинхронном коде (asyncio)

В асинхронных функциях исключение может находиться в разных местах:

async def async_func():
    try:
        await some_coroutine()
    except Exception as e:
        # Исключение из coroutine
        print(e)

# Исключение также может быть в Task
task = asyncio.create_task(async_func())
try:
    await task
except Exception as e:
    # Исключение из task
    pass

В traceback модуле

Для анализа исключений можно использовать модуль traceback:

import traceback

try:
    1 / 0
except ZeroDivisionError:
    # Получить текущий traceback
    traceback.print_exc()
    
    # Или получить его в виде строки
    tb_str = traceback.format_exc()
    print(tb_str)

Проверка наличия исключения

import sys

if sys.exc_info()[0] is not None:
    print("Текущее исключение существует")
else:
    print("Нет текущего исключения")

Этот код вернёт True только если мы находимся в блоке обработки исключения или в вызванных из него функциях.

Где может находиться исключение в Python? | PrepBro