pytool
pytool copied to clipboard
Python上下文管理器
两种实现方式:代码见gist
contextlib
这个库小而精, 可以实现很多功能,如回滚:
In [20]: @contextlib.contextmanager
....: def list_transaction(lis):
....: working = list(lis)
....: yield working
....: lis[:] = working
....:
In [21]: item = [1,2,3]
In [22]: with list_transaction(item) as working:
....: working.append(4)
....: working.append(5)
....: raise RuntimeError("oops")
....:
---------------------------------------------------------------------------
RuntimeError Traceback (most recent call last)
<ipython-input-22-1d3397fb1866> in <module>()
2 working.append(4)
3 working.append(5)
----> 4 raise RuntimeError("oops")
5
RuntimeError: oops
In [23]: item
Out[23]: [1, 2, 3]
在一个执行逻辑中当遇到异常则回滚。而平时使用的方式确实有修改就生效,直到抛出异常为止。
In [24]: for i in [4, 5]:
....: item.append(i)
....: raise RuntimeError("oops")
....:
---------------------------------------------------------------------------
RuntimeError Traceback (most recent call last)
<ipython-input-24-14821b16e499> in <module>()
1 for i in [4, 5]:
2 item.append(i)
----> 3 raise RuntimeError("oops")
4
RuntimeError: oops
In [25]: item
Out[25]: [1, 2, 3, 4]
但是其nested
方法貌似有点多余了,不太简洁,如:
import contextlib
with contextlib.nested(open('a.py', 'rb'),
open('b.py', 'wb')) as (reader, writer):
writer.write(reader.read())
with open('a.py', 'rb') as reader, \
open('c.py', 'wb') as writer:
writer.write(reader.read())