wing聊“Python进阶知识” - python with关键字详解

python学习网 2017-09-18 12:41:01

wing聊“Python进阶知识” - 系列文章导航页

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的优势了!
多线程相关知识这里不介绍,可以点击文章开头的链接,到导航页中查看我的另外一篇和多线程相关的文章

阅读(830) 评论(0)