我不知道为什么我们最终需要尝试……最后陈述。在我看来,这个代码块

try:
    run_code1()
except TypeError:
    run_code2()
other_code()

和这个finally的用法一样:

try:
    run_code1()
except TypeError:
    run_code2()
finally:
    other_code()

我遗漏了什么吗?


当前回答

我试图运行一个代码,我想读excel表。问题是,如果有一个文件没有表命名说:SheetSum我不能移动到错误的位置!!我写的代码是:

def read_file(data_file):
    # data_file = '\rr\ex.xlsx'
    sheets = {}
    try:
        print("Reading file: "+data_file)
        sheets['df_1'] = pd.read_excel(open(data_file,'rb'), 'SheetSum')
    except Exception as excpt:
        print("Exception occurred", exc_info=True)
    return sheets

read_file(file)
shutil.move( file, dirpath +'\\processed_files')

给出错误:

[WinError 32]进程无法访问文件,因为它正在运行 由其他进程使用

我必须添加完整的尝试,除了与finally块,并告诉最后,我需要在任何情况下关闭文件,如:

def read_file(data_file):
    # data_file = '\rr\ex.xlsx'
    sheets = {}
    sheets_file = None
    try:
        print("Reading file: "+data_file)
        sheets_file = open(data_file,'rb')
        sheets['df_1'] = pd.read_excel(sheets_file, 'SheetSum')
    except Exception as excpt:
        print("Exception occurred", exc_info=True)
    finally:
        if sheets_file:
            sheets_file.close()
    return sheets

read_file(file)
shutil.move( file, dirpath +'\\processed_files')

否则,文件仍然保持打开是后台。

如果出现finally,则指定一个清理处理程序。的尝试 子句,包括except和else子句。如果一个 异常发生在任何子句中而不被处理,则 异常被暂时保存。finally子句被执行。如果 有一个保存的异常,它在finally结束时被重新引发 条款。如果finally子句引发另一个异常,则保存 异常被设置为新异常的上下文。

..更多的在这里

其他回答

在第一个例子中,如果run_code1()引发了一个不是TypeError的异常,会发生什么?... Other_code()将不会被执行。

与finally: version: other_code()相比,无论引发任何异常,都保证执行。

如果你早点回来,情况就不一样了:

try:
    run_code1()
except TypeError:
    run_code2()
    return None   # The finally block is run before the method returns
finally:
    other_code()

与此相比:

try:
    run_code1()
except TypeError:
    run_code2()
    return None   

other_code()  # This doesn't get run if there's an exception.

其他可能导致差异的情况:

如果在except块内抛出异常。 如果在run_code1()中抛出异常,但它不是TypeError。 其他控制流语句,如continue和break语句。

它们不相等。最后,不管发生什么,代码都会运行*。 它对于清理必须运行的代码非常有用。


*: 正如Mark Byers所评论的,任何导致进程立即终止的事情也会阻止最终代码的运行。 后者可以是os._exit()。或断电,但无限循环或其他东西也属于这一类。

专业地使用delphi几年教会了我如何使用最后来保护我的清理程序。Delphi在很大程度上强制使用finally来清理try块之前创建的任何资源,以免导致内存泄漏。这也是Java、Python和Ruby的工作原理。

resource = create_resource
try:
  use resource
finally:
  resource.cleanup

不管你在try和finally之间做了什么,资源都会被清理。此外,如果执行从未到达try块,它将不会被清理。(例如create_resource本身抛出异常)它使你的代码“异常安全”。

至于为什么你需要一个finally块,并不是所有的语言都需要。在c++中,你可以自动调用析构函数,当异常展开堆栈时,析构函数会强制执行清理。我认为与尝试相比,这是朝着更干净的代码方向迈进了一步。最后的语言。

{    
  type object1;
  smart_pointer<type> object1(new type());
} // destructors are automagically called here in LIFO order so no finally required.

最后是“清理行动”的定义。finally子句在离开try语句之前的任何事件中执行,无论是否发生异常(即使您没有处理它)。

我赞同拜尔斯的例子。