Укажите контекст исключения (`причина`), не вызывая его - PullRequest
0 голосов
/ 06 апреля 2020

Мы используем библиотеку, которая представляет общее состояние сбоя (ресурс не найден), вызывая исключение (SnafuException). Мы склонны обрабатывать это с помощью шаблона, который немного варьируется от использования к использованию:

try:
    foo()
except SnafuException as se:
    log.exception("message", exc_info=se)
    raise FubarException("message")

Как я понимаю, установка exc_info = se не обязательна для log.exception, но эти сообщения может понизиться.

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

def utility(data: Data,
            handler: Callable[[SnafuException], Exception] = default_handler):
    try:
        work_in_progress = foo(data)
    except SnafuException as se:
        raise handler(se)
    return finish(work_in_progress)

Проблема в написании default_handler; ему нужно вернуть исключение , и я бы хотел, чтобы это возвращенное исключение имело в качестве родителя (контекст или причина) аргумент se. Учитывая характер работы (мы - большая группа из 1041 человек, и есть другие команды, которые могут работать в тех же репозиториях, которыми мы обычно управляем), я хотел бы получить решение, которое где-то задокументировано.

Как мне написать return FubarException("message", cause=se)?

Некоторые параметры могут быть в порядке, но я не доволен:

  • Повышение изнутри обработчика. Это затруднит передачу лямбды в качестве обработчика.
  • Назначение контекста вне обработчика. Это, вероятно, будет работать нормально, но мне кажется, что назначение контекста является частью работы обработчика, поэтому это должно происходить внутри обработчика.
  • Буквально присваивая handler_return_value.__cause__ = se внутри обработчика. Это задокументировано в PEP 3134 , так что это хорошо. Но он использует атрибут protected / magi c, а PEP - с 2005 года, поэтому, если это «правильный» способ сделать это, я бы ожидал, что он уже задокументирован в другом месте.
  • Перемещение try: ... except: ... внутри функции-обработчика, которая будет принимать функцию "действия" foo в качестве аргумента. Это, безусловно, позволило бы свести рассматриваемый паттерн настолько полно, насколько это возможно, но я боюсь, что он запутает основной поток выполнения, не будет достаточно гибким для использования во многих случаях и / или потребует большого количества лямбда-выражений.

Любой совет?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...