1、with解决了什么问题
先看一段传统的文件操作相关代码(假如文件打开过程不发生异常):
#!/usr/bin/env python
# -*- coding: utf-8 -*-
try:
f = open('/root/a.txt', 'r')
for eachLine in f:
print eachLine
finally:
f.close()
如上,可以发现为了程序的健壮性,我们需要考虑是否发生异常都执行close操作
先看看使用with语句之后代码的样子:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
with open('/root/a.txt', 'r') as f:
for eachLine in f:
print eachLine
with语句可以实现简化资源费配和释放相关操作,一定程度去掉try-except-finally关键字
2、with的工作原理
一个对象支持with语句操作,前提是这个对象支持上下文管理协议,比如如下一些对象:
- file
- decimal.Context
- thread.LockType
- threading.Lock
- threading.RLock
- threading.Condition
- threading.Semaphore
- threading.BoundedSemaphore
显然是这些对象内有一些额外的代码支持了这个操作
上下文管理协议先不介绍,一般场景我们更多是使用with而不需要定义一个可以和with一起工作的类。
3、多线程同步锁中使用with
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import threading
from time import sleep
count = 0
c_lock = threading.Lock()
def add():
global count
sleep(1)
with c_lock:
if count < 2:
count += 1
print count
threads = list()
for i in range(3):
t = threading.Thread(target=add)
threads.append(t)
for t in threads:
t.start()
上面代码我们关注一下这一段
with c_lock:
if count < 2:
count += 1
不使用with的时候我们是这样写的:
if c_lock.acquire():
if count < 2:
count += 1
c_lock.release()
其实还不够,因为万一数据操作过程中发生异常,release方法没有被调用到,咋个办?所以实际使用的时候可能要这样写:
try:
if c_lock.acquire():
if count < 2:
count += 1
finally:
c_lock.release()
这个时候就更加能够体现出with的优势了!
多线程相关知识这里不介绍,可以点击文章开头的链接,到导航页中查看我的另外一篇和多线程相关的文章