python一个try块后接一个或多个finally块_Effective Python(13): 合理利用try/except/else/finally结构中的每个代码块...

一、Python的异常处理机制

Python的异常处理要考虑四种不同的时机,可用try、except、else和finally块来表述。

1. finally块

如果:

既要将异常向上传播

又要在异常发生时执行清理操作

那就可以使用try/finally结构。

这种结构有一项常见的用途,就是确保程序能够可靠地关闭文件句柄(还有另外一种写法,参见第43条)

handle = open("/tmp/random_data.txt") # May raise IOError

try:

data = handle.read() # May raise UnicodeDecodeError

finally:

handle.close()

上面的代码中:

read方法所抛出的异常会向上传播给调用方,而finally块中的handle.close方法则一定能执行

open方法必须放在try块外面,因为如果打开文件时发生异常(例如,由于找不到该文件而抛出IOError),那么程序应该跳过finally块

2. else块

如果try块没有发生异常,那么就执行else块。

有了这种else块,就可以尽量缩减try块内的代码量,使其更加易读。

举例

例如,要从字符串中加载JSON字典数据,然后返回字典里某个键所对应的值

import json

def load_json_key(data, key):

try:

result_dict = json.load(data) # may raise ValueError

except ValueError as e:

raise KeyError from e

else:

return result_dict[key] # may raise KeyError

如果不是有效的JSON格式,那么就用json.loads解码时,会产生ValueError。

如果能够解码,那么else块里的查找语句就会执行,他会根据键来查出相关的值。

查询时若有异常,则该异常会向上传播

这种else子句,会把try/except后面的内容和except块本身区分开,使异常的传播行为变得更加清晰。

3. 混合使用

如果要在符合语句中把上面几种机制都用到,那就编写完整的try/except/else/finally结构。

举例

例如,要从文件中读取某项事物的描述信息,处理该事物,然后就地更新该文件。

UNDEFINED = object()

def divide_json(path):

handle = open(path, "r+") # May raise IOError

try:

data = handle.read() # May raise UnicodeDecodeError

op = json.loads(data) # May raise ValueError

value = (op["numerator"] / op["denominator"]) # May raise ZeroDivisionError

except ZeroDivisionError as e:

return UNDEFINED

else:

op["result"] = value

result = json.dumps(op)

handle.seek(0)

handle.write(result) # May raise IOError

return value

finally:

handle.close() # Always Run

二、总结

无论try块是否发生异常,都可利用try/finally复合语句中的finally块来执行清理工作

else块可以用来缩减try块中的代码量,并没有把发生异常时所要执行的语句与try/except代码块隔开

顺利运行try块后,若想使某些操作能在finally块的清理代码之前执行操作,则可将这些操作写到else块中

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值