功能说明
Store.transaction() 是一个基于 @contextmanager 的事务边界。进入时复制一份字典快照,正常退出时只增加提交计数;只要代码块里抛出任何异常,就把字典恢复成快照、增加回滚计数,并把原异常继续抛出。示例先做一次成功写入,再模拟支付失败,展示数据在异常后回到事务开始前的状态。
关键代码
snapshot = dict(self.data)
tx = Transaction(self)
try:
yield tx
except BaseException:
self.data = snapshot
self.rollbacks += 1
raise
else:
self.commits += 1
捕获 BaseException 是为了让 KeyboardInterrupt 和 SystemExit 也触发回滚;如果只捕获 Exception,中断时数据会停留在半更新状态。
使用注意
- 快照是浅拷贝,嵌套的可变对象仍被共享;需要深拷贝时改用
copy.deepcopy。 - 事务对象只是操作入口,没有隔离级别,也不支持并发写;多线程场景需要额外加锁。
- 回滚会替换整个字典,外部持有的旧字典引用不会自动更新。
- 提交阶段没有持久化动作,真实项目应在
else分支里写文件或提交数据库。 - 不要在事务里吞掉异常再继续,否则上下文管理器会认为操作成功并提交。
验证方式
运行输出应依次显示提交后的余额与币种、回滚提示,以及回滚后的原始数据;commits 为 1、rollbacks 为 1。可以再加一个 raise 场景,确认异常类型和消息原样抛出。