本文发自 http://www.binss.me/blog/talk-about-the-with-usage-in-python/,转载请注明出处。
在阅读ioloop源码时看到以下语句:
with self._callback_lock:
callbacks = self._callbacks
self._callbacks = []
# _callback_lock是互斥锁,即threading.Lock()
额,对于加锁,我的第一反应是这样的:
lock = threading.Lock()
# 加锁
lock.acquire()
do something
# 解锁
lock.release()
那如果do something出错了怎么办?使用try...except...finally呗:
lock = threading.Lock()
lock.acquire()
try:
do something
except:
print “error"
finally:
lock.release()
然而python提供了更优雅的方法——with:
The ‘with‘ statement clarifies code that previously would use try...finally blocks to ensure that clean-up code is executed.
The ‘with‘ statement is a control-flow structure whose basic structure is:
with expression [as variable]: with-block
The expression is evaluated, and it should result in an object that supports the context management protocol (that is, has __enter__() and __exit__() methods).
The object’s __enter__() is called before with-block is executed and therefore can run set-up code. It also may return a value that is bound to the name variable, if given. (Note carefully that variable is not assigned the result of expression.)
After execution of the with-block is finished, the object’s __exit__() method is called, even if the block raised an exception, and can therefore run clean-up code.
就是说要使用with语句的表达式(对象)必须实现__enter__()
和__exit__()
,然后__enter__()
会在with-block执行之前调用,__exit__()
会在with-block执行完毕后调用,无论with-block是否抛出异常。
然后看看lock.py
def __enter__(self):
return self.acquire()
def __exit__(self, typ, value, tb):
self.release()
好吧,果然如此,果然很方便很优雅。那么as variable又是干什么用的呢?
根据文档:
with open('/etc/passwd', 'r') as f: for line in f: print line
variable是用来接收__enter__()
返回的对象的。在这里,f接受了file的__enter__()
的返回对象,从而能够迭代输出每一行。
如果系统没有帮我们实现__enter__()
和__exit__()
,我们可以自己实现:
class DoTest:
def __init__(self):
self.count = 100
def __enter__(self):
print "enter"
return self.count
def __exit__(self, typ, value, tb):
print "exit"
a = DoTest()
with a as l:
print "do something error"
print l
raise Exception
输出为:
enter
do something error
100
exit
Traceback (most recent call last):
File "/Users/bin/Desktop/TestCode/test.py", line 28, in <module>
raise Exception
Exception
参考文章 https://docs.python.org/2/whatsnew/2.6.html#pep-343-the-with-statement