处理多个异常时共享Python代码

时间:2016-01-14 18:14:27

标签: python exception exception-handling

我编写了一个需要处理可以抛出多个异常的函数的程序。对于我捕获的每个异常,我都有一些代码可以专门处理它。

但是,无论遇到哪个异常,我还有一些我想要运行的代码。我当前的解决方案是handle_exception()函数,该函数从每个except块调用。

try:
    throw_multiple_exceptions()
except FirstException as excep:
    handle_first_exception()
    handle_exception()
except SecondException as excep:
    handle_second_exception()
    handle_exception()

有更好的方法吗? 我希望代码看起来像这样:

try:
    throw_multiple_exceptions()
except FirstException as excep:
    handle_first_exception()
except SecondException as excep:
    handle_second_exception()
except Exception as excep:
    handle_exception()

4 个答案:

答案 0 :(得分:8)

PEP 0443怎么样?它非常棒,而且非常可扩展,因为您只需要编写代码并注册新的处理程序

from functools import singledispatch
@singledispatch
def handle_specific_exception(e): # got an exception we don't handle
    pass       

@handle_specific_exception.register(Exception1)
def _(e):
    # handle exception 1

@handle_specific_exception.register(Exception2)
def _(e):
    # handle exception 2

try:
    throw_multiple_exceptions()
except Exception as e:
    handle_specific_exception(e)
    handle_exception()

答案 1 :(得分:5)

您可以执行以下操作:

try:
    throw_multiple_exceptions()
except FirstException, SecondException as excep:
    if isinstance(excep, FirstException):
        handle_first_exception()
    else:
        handle_second_exception()
    handle_exception()

答案 2 :(得分:1)

您可以创建一个通用例程并传递其他可调用对象(函数),具体取决于引发的异常类型。

$ecdClosureStatus = getClosureChartData('ECD');
    $ChartNameOrNum = 'chart3'; // Title of the shape that embeds the chart
    $ChartRef = 'chart3'; // Title of the shape that embeds the chart
    $SeriesNameOrNum = 'Series 1';
    $NewLegend = "Closed On Time";
    $NewValues =    array(array('Closed On Time', 'Closed Late'), array(
                                        (int)$ecdClosureStatus['ClosedOnTime'],
                                        0
                                    ));
    $TBS->PlugIn(OPENTBS_CHART, $ChartNameOrNum, $SeriesNameOrNum, $NewValues, $NewLegend);

    $SeriesNameOrNum = 'Series 2';
    $NewLegend =    '1-30 Days Late';
    $NewValues =        array(array('Closed On Time', 'Closed Late'), array(
                                        0,
                                        (int)$ecdClosureStatus['OneToThirtyDaysLate']
                                    ));
    $TBS->PlugIn(OPENTBS_CHART, $ChartNameOrNum, $SeriesNameOrNum, $NewValues, $NewLegend);

    $SeriesNameOrNum = 'Series 3';
    $NewLegend =        ' 31-60 Days Late';
    $NewValues =        array(array('Closed On Time', 'Closed Late'), array(
                                        0,
                                        (int)$ecdClosureStatus['ThirtyOneToSixtyDaysLate']
                                    ));
    $TBS->PlugIn(OPENTBS_CHART, $ChartNameOrNum, $SeriesNameOrNum, $NewValues, $NewLegend);

    $SeriesNameOrNum = 'Series 4';
    $NewLegend =    '61-90 Days Late';
    $NewValues =            array(array('Closed On Time', 'Closed Late'), array(
                                        0,
                                        (int)$ecdClosureStatus['SixtyOneToNinetyDaysLate']
                                    ));
    $TBS->PlugIn(OPENTBS_CHART, $ChartNameOrNum, $SeriesNameOrNum, $NewValues, $NewLegend);

    $SeriesNameOrNum = 'Series 5';
    $NewLegend = ' >90 Days Late';
    $NewValues =        array(array('Closed On Time', 'Closed Late'), array(
                                        0,
                                        (int)$ecdClosureStatus['MoreThanNinetyDaysLate']
                                    ));
    $TBS->PlugIn(OPENTBS_CHART, $ChartNameOrNum, $SeriesNameOrNum, $NewValues, $NewLegend);

虽然我会就评论讨论达成一致,但很多例外情况与很多不同的条款似乎有点像代码味道。

答案 3 :(得分:1)

如果有很多例外需要处理,我建议如下:

from exceptions import ZeroDivisionError, AssertionError, Exception

def handle_first_exception():
    print "First exception occurred"

def handle_second_exception():
    print "Second exception occurred"

def handle_exception():
    print "Exception occurred"

def throw_multiple_exceptions():    
    3/0                 # |-> will output "First exception occurred"
    assert 2 > 3        # |-> will output "Second exception occurred"
    [1, 2, 3].index(0)  # |-> will output "Exception occurred" 

if __name__ == '__main__':
    # more types of exceptions could be added to this dict
    exceptions = { ZeroDivisionError: handle_first_exception, AssertionError: handle_second_exception }

    try:
        throw_multiple_exceptions()
    except Exception as excep:
        if type(excep) in exceptions.keys():
            exceptions[type(excep)]()
        else:  handle_exception()