Answers:
如果您提早返回,会有所不同:
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.
可能导致差异的其他情况:
run_code1()
但不是TypeError
。continue
和break
语句。您可以finally
用来确保文件或资源被关闭或释放,而不管是否发生异常,即使您没有捕获到该异常也是如此。(或者,如果您没有捕获到该特定异常。)
myfile = open("test.txt", "w")
try:
myfile.write("the Answer is: ")
myfile.write(42) # raises TypeError, which will be propagated to caller
finally:
myfile.close() # will be executed before TypeError is propagated
在此示例中,使用该with
语句会更好,但是这种结构可以用于其他类型的资源。
几年后,我写了一篇博客文章,讲述滥用finally
读者可能会觉得有趣的事情。
它们不相等。不管其他什么情况发生,最终代码都会运行。这对于必须运行的清理代码很有用。
Finally code is run no matter what else happens
...除非存在无限循环。或断电。或者os._exit()
。还是……
os._exit
。
除了上面的其他答案外,该finally
子句无论执行什么都将else
执行,而该子句仅在未引发异常的情况下才执行。
例如,无例外地写入文件将输出以下内容:
file = open('test.txt', 'w')
try:
file.write("Testing.")
print("Writing to file.")
except IOError:
print("Could not write to file.")
else:
print("Write successful.")
finally:
file.close()
print("File closed.")
输出:
Writing to file.
Write successful.
File closed.
如果有异常,代码将输出以下内容(请注意,故意使文件保持只读状态会导致错误。
file = open('test.txt', 'r')
try:
file.write("Testing.")
print("Writing to file.")
except IOError:
print("Could not write to file.")
else:
print("Write successful.")
finally:
file.close()
print("File closed.")
输出:
Could not write to file.
File closed.
我们可以看到,该finally
子句无论有无异常都会执行。希望这可以帮助。
else
是一回事。有用的知道。
代码块不是等效的。finally
如果run_code1()
引发除以外的异常TypeError
,或者run_code2()
引发异常,则该子句也将运行,而other_code()
在这些情况下,在第一个版本中则不会运行该子句。
如文档中所述,该finally
子句旨在定义在所有情况下都必须执行的清理操作。
如果
finally
存在,则指定“清理”处理程序。该try
子句被执行,包括anyexcept
和else
子句。如果在任何子句中发生异常并且未进行处理,则将临时保存该异常。该finally
子句被执行。如果存在已保存的异常,则会在finally
子句末重新引发。
一个例子:
>>> def divide(x, y):
... try:
... result = x / y
... except ZeroDivisionError:
... print("division by zero!")
... else:
... print("result is", result)
... finally:
... print("executing finally clause")
...
>>> divide(2, 1)
result is 2.0
executing finally clause
>>> divide(2, 0)
division by zero!
executing finally clause
>>> divide("2", "1")
executing finally clause
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in divide
TypeError: unsupported operand type(s) for /: 'str' and 'str'
如您所见,该finally
子句在任何情况下都会执行。在TypeError
通过将两个字符串凸起不被处理except
子句和后因此再次加注finally
条款已经被执行。
在实际的应用程序中,无论是否成功使用资源,finally子句对于释放外部资源(例如文件或网络连接)都是有用的。
完美的例子如下:
try:
#x = Hello + 20
x = 10 + 20
except:
print 'I am in except block'
x = 20 + 30
else:
print 'I am in else block'
x += 1
finally:
print 'Finally x = %s' %(x)
当您要在运行主要工作的代码之前运行“可选”代码并且可选代码可能由于各种原因而失败时,也可以使用Final。
在下面的示例中,我们不确切知道store_some_debug_info
可能会引发哪种异常。
我们可以运行:
try:
store_some_debug_info()
except Exception:
pass
do_something_really_important()
但是,大多数的短毛猫都会抱怨捉摸不清一个例外。另外,由于我们选择仅pass
针对错误,因此该except
块并没有真正增加价值。
try:
store_some_debug_info()
finally:
do_something_really_important()
上面的代码与第一个代码块具有相同的效果,但更为简洁。
几年来专业地使用delphi教会了我维护最终使用的清理例程。Delphi几乎会强制使用finally来清理在try块之前创建的所有资源,以免引起内存泄漏。这也是Java,Python和Ruby的工作方式。
resource = create_resource
try:
use resource
finally:
resource.cleanup
不管您在尝试和最终之间进行什么操作,资源都会被清理。另外,如果执行从未到达该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.
一个try块只有一个强制性子句:try语句。else,else和finally子句是可选的,并且基于用户首选项。
最终:在Python离开try语句之前,它将在任何情况下在finally块中运行代码,即使它正在结束程序。例如,如果Python在except或else块中运行代码时遇到错误,则在停止程序之前,finally块仍将执行。
运行以下Python3代码以最终了解最终需求:
情况1:
count = 0
while True:
count += 1
if count > 3:
break
else:
try:
x = int(input("Enter your lock number here: "))
if x == 586:
print("Your lock has unlocked :)")
break
else:
print("Try again!!")
continue
except:
print("Invalid entry!!")
finally:
print("Your Attempts: {}".format(count))
案例2:
count = 0
while True:
count += 1
if count > 3:
break
else:
try:
x = int(input("Enter your lock number here: "))
if x == 586:
print("Your lock has unlocked :)")
break
else:
print("Try again!!")
continue
except:
print("Invalid entry!!")
print("Your Attempts: {}".format(count))
每次尝试以下输入:
**在学习Python的初期。
我试图在要阅读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]该进程无法访问文件,因为该文件正在被另一个进程使用
我必须添加完整的try except with finally
块并告诉finally
我在任何情况下都需要关闭文件:
def read_file(data_file):
# data_file = '\rr\ex.xlsx'
sheets = {}
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:
sheets_file.close()
return sheets
read_file(file)
shutil.move( file, dirpath +'\\processed_files')
否则,文件仍然保持打开状态。
如果
finally
存在,则指定清除处理程序。该try
子句被执行,包括anyexcept
和else
子句。如果在任何子句中发生异常并且未对其进行处理,则将临时保存该 异常。该finally
子句被执行。如果存在已保存的异常,则会在finally
子句末重新引发。如果finally
子句引发另一个异常,则将保存的异常设置为新异常的上下文。
..更多这里