Pythonic способ выполнения общих действий для всех пойманных исключений - PullRequest
3 голосов
/ 06 марта 2019

Если у меня следующая структура:

try:
    do_something_dangerous()
except Exception1:
    handle_exception1()
    handle_all_exceptions()
except Exception2:
    handle_exception2()
    handle_all_exceptions()
...

Какой самый Pythonic способ позвонить handle_all_exceptions, если я не хочу делать это в каждом предложении except, потому что у меня их много? Может быть, есть простой способ определить, произошло ли исключение в предложении finally?

Ответы [ 4 ]

4 голосов
/ 06 марта 2019

Самый простой способ, который я могу представить, это вложение операторов try:

try:
   try:
        do_something_dangerous()
    except Exception1:
        handle_exception1()
        raise
    except Exception2:
        handle_exception2()
        raise
except Exception:
    handle_all_exceptions()

Голый raise поднимает исключение.

Другой вариант - перехватить все исключения и выполнить собственную диспетчеризацию вместо использования оператора try для этого:

try:
    do_something_dangerous()
except Exception as e:
    if isinstance(e, Exception1):
        handle_exception1()
    if isisntance(e, Exception2):
        handle_exception2()
    handle_all_exceptions()
2 голосов
/ 06 марта 2019

Я думаю, вы также можете проверить типы исключений.Однако я не знаю, является ли это наиболее питоническим способом:

РЕДАКТИРОВАТЬ: Глядя на документацию, кажется, что не самый питонический способ.Как вы справляетесь с различными типами исключений внутри вашей функции handle_all_exceptions() зависит от вас. См. Документ.

try:
    do_something_dangerous()
except Exception as e:
    handle_all_exceptions(e)

def handle_all_exceptions(e):
    if isinstance(e, Exception1):
        handle_exception1()
    elif isinstance(e, Exception2):
        handle_exception2()

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

ex = []
try:
    do_something_dangerous()
except Exception1 as e:
    ex.append(e)
    handle_exception1()
except Exception2 as e:
    ex.append(e)
    handle_exception2()
finally:
    if ex: handle_all_exceptions(ex)
1 голос
/ 06 марта 2019

Сначала вы можете определить функцию обработки сопоставления сопоставления с соответствующим исключением:

err_handling = {
   Exception1: handle_exception1
   Exception2: handle_exception2
   # ...
}

Затем вы можете принять возбужденное исключение в качестве аргумента функции handle_all_exceptions и добавить его в специальную обработку, используяобработка отображения и тип возбужденного исключения.

def handle_all_exceptions(err):
    # common exception handling
    err_handling[type(err)]()

Делая это, вы можете обработать исключение простым способом:

try:
    do_something_dangerous()
except Exception as err:
    handle_all_exceptions(err)
0 голосов
/ 07 марта 2019

Я нашел какое-то хитрое решение без type, isinstance и лотов raise в каждом предложении except. Может быть, это не самый Pythonic, но это по крайней мере интересно:

try:
    do_something_dangerous()
except:
    try:
        raise
    except Exception1:
        handle_exception1()
    except Exception2:
        handle_exception2()
    handle_all_exceptions()
...