3

使用tryandexcept进行错误处理时,是否显式调用finally或只是转到从异常代码中删除的新行是否重要?例如,是否存在以下两个函数会产生不同结果的情况?

#Function 1 with finally
def final(x):
    try:
        print(x*x)

    except:
        print("Error")

    finally:
        print("End Function")


#Function 2 with new line dedent
def dedent(x):
    try:
        print(x*x)

    except:
        print("Error")

    print("End Function")

更新: 感谢您解释finally运行即使except块中有错误。我想指出的另一件事是,finally即使您在 except 块中返回一个对象,该块也会运行。例如,下面的函数 3 即使在return函数 4 不会打印之后也会打印。

#Function 3 with finally
def final(x):
    try:
        print(x*x)

    except:
        return 3

    finally:
        print("End Function 3")


#Function 4 with new line dedent
def dedent(x):
    try:
        print(x*x)

    except:
        return 3

    print("End Function 4")

test1 = final('test')
test2 = dedent('test')
4

4 回答 4

3

except已经提到的块中有错误:

def final(x):
    try:
        print(x*x)

    except:
        print("Error")
        damnit

    finally:
        print("End Function")

def dedent(x):
    try:
        print(x*x)

    except:
        print("Error")
        damnit

    print("End Function")

try:
    final("a")
except Exception as e:
    print("There was an error:", e)
#>>> Error
#>>> End Function
#>>> There was an error: global name 'damnit' is not defined

try:
    dedent("a")
except Exception as e:
    print("There was an error:", e)
#>>> Error
#>>> There was an error: global name 'damnit' is not defined

还有return行为:

def final(x):
    try:
        print(x*x)

    except:
        print("Error")
        return "Return inside"

    finally:
        print("End Function")
        return "Return outside"

def dedent(x):
    try:
        print(x*x)

    except:
        print("Error")
        return "Return inside"

    print("End Function")
    return "Return outside"

try:
    final("a")
except Exception as e:
    print("There was an error:", e)
#>>> Error
#>>> End Function
#>>> 'Return outside'

try:
    dedent("a")
except Exception as e:
    print("There was an error:", e)
#>>> Error
#>>> 'Return inside'
于 2013-09-26T21:30:56.860 回答
1

finally:即使except处理程序引发异常,第一个版本仍将运行该套件。在第二个版本中,finalprint()不会在这种情况下执行

>>> def print(*args, **kw):
...     if not args or args[0] != 'End Function':
...         raise ValueError("Only print End Function!")
...     __builtins__.print(*args, **kw)
... 
>>> final(0)
End Function
Traceback (most recent call last):
  File "<stdin>", line 3, in final
  File "<stdin>", line 3, in print
ValueError: Only print End Function!

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 5, in final
  File "<stdin>", line 3, in print
ValueError: Only print End Function!
>>> dedent(0)
Traceback (most recent call last):
  File "<stdin>", line 3, in dedent
  File "<stdin>", line 3, in print
ValueError: Only print End Function!

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 5, in dedent
  File "<stdin>", line 3, in print
ValueError: Only print End Function!

请注意,打印的第一final(0)件事是End Function; 没有为 打印这样的文本dedent(0)

你永远不需要显式地执行一个finally:套件;它总是运行,即使您要提前退出函数return,或者使用 跳出循环break或使用continue跳过循环体的其余部分:

>>> while True:
...     try:
...         print("In an infinite loop?")
...         break
...     finally:
...         print("Executed before the loop ends")
... 
In an infinite loop
Executed before the loop ends

引用try声明文档

如果finally存在,它指定一个“清理”处理程序。该try子句被执行,包括任何exceptelse子句。如果任一子句发生异常且未处理,则暂时保存该异常。finally子句被执行。finally如果存在已保存的异常,则会在子句末尾重新引发。

return, breakorcontinue语句在...语句try套件中执行时,该子句也将在“退出时”执行。</p> tryfinallyfinally

于 2013-09-26T21:23:16.930 回答
1

根据PEP 341

try:
    block-1 ...
except Exception1:
    handler-1 ...
except Exception2:
    handler-2 ...
else:
    else-block
finally:
    final-block

块 1 中的代码被执行。如果代码引发异常,则测试各种异常块:如果异常属于 Exception1 类,则执行 handler-1;否则,如果它属于 Exception2 类,则执行 handler-2,依此类推。如果没有引发异常,则执行 else 块。

无论之前发生了什么,一旦代码块完成并处理任何引发的异常,就会执行最终块。即使在异常处理程序或 else 块中出现错误并且引发了新异常,最终块中的代码仍会运行。

所以正如Martjin所说,即使except引发另一个错误,finally中的代码也会被执行。

于 2013-09-26T21:27:04.723 回答
1

如果在所有地方都引发异常,差异就很明显了。

如果只有 try 块引发错误,那么它们是相同的。

#Function 1 with finally
def final(x):
    try:
        print(x*x)
        raise Exception
    except:
        print("Error")    
    finally:
        print("End Function")


#Function 2 with new line dedent
def dedent(x):
    try:
        print(x*x)
        raise Exception
    except:
        print("Error")    
    print("End Function")

final(10)
dedent(10)

然而。如果 except 块也引发错误,则 finally 块保证运行。

#Function 1 with finally
def final(x):
    try:
        print(x*x)
        raise Exception
    except:
        print("Error")
        raise Exception
    finally:
        print("This will be printed")

#Function 2 with new line dedent
def dedent(x):
    try:
        print(x*x)
        raise Exception
    except:
        print("Error")
        raise Exception
    print("This will not be printed")
final(10)
dedent(10)
于 2013-09-26T21:31:21.110 回答