需求场景
在执行完对资源的操作后再执行一些动作,若此动作执行失败,需要对之前对资源的操作进行回退。
示例
在执行完do_something_to_db
函数后,需要执行after_do_db
函数,但是当after_do_db
函数执行错误,需要对do_something_to_db
函数之前所做的操作进行清理、回退
这时使用with
语句可以比较方便的进行回退操作,相对于不加with
的语句显得优雅许多不用每次调用after_do_db
时都加try...except..
.回退清理代码
代码
class BaseException(Exception):
message = "This is the base Exception"
def __init__(self, **kw):
self.msg = self.message % kw
def __str__(self):
return self.msg
class MyExcep(BaseException):
message = ("error is: %(name)s, reason is %(reason)s")
def do_db(param1, param2):
print("do db")
print(param1, param2)
return 123
def un_do_db(param1, param2):
print("undo db")
def after_do_db(r):
print(r)
# return True
raise Exception("Error")
@contextlib.contextmanager
def do_something_to_db(param1, param2):
res = do_db(param1, param2)
try:
yield res
except Exception:
un_do_db(param1, param2)
raise MyExcep(name="Error", reason="the db action is Error")
使用
# 使用with版本
with do_something_to_db('123', '345') as r:
after_do_db(r)
# 不使用with版本
param1 = '123'
param2 = '345'
res = do_something_to_db(param1 , param2)
try:
after_do_db(res)
except Exception as e:
un_do_db(param1, param2)