与try / except / finally语句的等价

时间:2017-09-14 23:47:06

标签: python python-3.x exception-handling try-catch programming-languages

从坚果壳中的Python

  

try / except / finally语句,例如:

try:
    ...guarded clause...
except ...expression...:
    ...exception handler code...
finally:
    ...clean-up code...
     

等同于嵌套语句:

try:
    try:
        ...guarded clause...
    except ...expression...:
        ...exception handler code...
finally:
    ...clean-up code...
  1. 为什么它等同于嵌套表单?
  2. 是否可以写成等同于没有finally的表单?

    是否相当于

    try:
        ...guarded clause...
    except ...expression...:
        ...exception handler code...
        ...clean-up code...
    ...clean-up code...
    
  3. 感谢。

3 个答案:

答案 0 :(得分:1)

不,您的替代代码与try / except / finally版本不完全相同。要了解原因,请考虑如果在示例的...exception handler code...部分内触发了第二个异常会发生什么。

这是一个显示问题的演示:

try:
    print('in try')     # guarded code
    1/0                 # oops, a bug
except ZeroDivisionError:
    print('top of except')  # exception handling code
    name_does_not_exist     # oops, the exception handling code is buggy too
    print('end of except')  # this is a bad place for cleanup code
finally:
    print('in finally')   # this is a much better place to do cleanup

输出:

in try
top of except
in finally
Traceback (most recent call last):

  File "<ipython-input-17-63590fc64963>", line 6, in <module>
    name_does_not_exist     # oops, the exception handling code is buggy too

NameError: name 'name_does_not_exist' is not defined

请注意,永远不会打印end of except消息,因为NameError发生在上一行。如果line是关键的清理代码,那么只有tryexcept的程序将无法运行它。如果您将清理代码放在finally块中,则无论代码的任何其他部分引发任何异常,都可以保证运行。

答案 1 :(得分:1)

  1. 因为它是如何定义的。因为以这种方式定义它是有用和标准的,并且因为没有其他有用的方法来定义它。
  2. 是的,但不是你的方式。

    try:
        do_stuff()
    except OneProblem:
        handle_it()
    except DifferentProblem:
        handle_that()
    finally:
        cleanup()
    

    相当于

    try:
        try:
            do_stuff()
        except OneProblem:
            handle_it()
        except DifferentProblem:
            handle_that()
    except:
        # Clean up if an unhandled exception happened, then restore the exception.
        cleanup()
        raise
    # Also clean up if we're not propagating an exception.
    cleanup()
    
  3. 就清理而言总是发生并且永远不会发生两次,尽管异常链接和追溯等行为可能表现不同。

答案 2 :(得分:0)

这就是我为避免为finally代码创建函数而不得不从两个不同的地方调用它的目的。

try:
    pass
    pass
    1/0
    pass
    pass
    pass
    raise Exception('Success')
except Exception, e:
    if e.message != 'Success':
        import traceback
        print traceback.format_exc()

    print 'in finally'
    print 'in finally'
    print 'in finally'

    if e.message != 'Success':
        raise


在Linux上的输出:

Traceback (most recent call last):
  File "./test_finally.py", line 34, in <module>
    1/0
ZeroDivisionError: integer division or modulo by zero

in finally
in finally
in finally
Traceback (most recent call last):
  File "./test_finally.py", line 34, in <module>
    1/0
ZeroDivisionError: integer division or modulo by zero

shell returned 1