1、with操作符

在python中读写文件,可能需要这样的代码

try-finally读写文件

file_text = None
try:
file_text = open('./text', 'r')
print file_text.read()
except IOError, ex:
traceback.print_exc()
finally:
if file_text:
file_text.close()

同样,在python中使用线程锁,可能需要这样的代码

try-finally线程锁

lock = threading.Lock()
lock.acquire()
try:
pass
except Exception, ex:
traceback.print_exc()
finally:
lock.release()

可能你会觉得这种写法很不方便,python提供了with操作符,你可以这样操作

with读写文件

with open('./text', 'r') as file_text:
print file_text.read()

with线程锁

with lock:
pass

是不是方便多了。

其实,不只是lock和file可以使用with操作符。

实际上,任何对象,只要正确实现上下文管理,就可以使用with语句。实现上下文管理是通过 __enter__ 和 __exit__ 这两个方法实现的。

2、上下文管理

上下文管理可以为我们屏蔽上下文的复杂性。例如,我们实现一个类Cat,实现其__enter__和__exit__方法。

__enter__(self): 进入上下文管理器时调用此方法,其返回值将被放入with-as语句中as说明符指定的变量中。

__exit__(self,type,value,tb):离开上下文管理器调用此方法。如果有异常出现,type、value、tb分别为异常的类型、值和追踪信息。如果没有异常,

3个参数均设为None。此方法返回值为True或者False,分别指示被引发的异常得到了还是没有得到处理。如果返回False,引发的异常会被传递出上下文。

如下。

class Cat(object):

    def __init__(self, name):
self.name = name def __enter__(self):
print 'enter from Cat named %s' % self.name
return self def hello(self):
print 'hello, %s' % self.name def __exit__(self, exc_type, exc_val, exc_tb):
print 'exit from Cat named %s' % self.name

执行,并打印结果

with Cat('Tom') as tom:
tom.hello() enter from Cat named Tom
hello, Tom
exit from Cat named Tom

这里我们执行as tom获得了Cat类的一个实例,这是通过__enter__方法的返回得到的。

当然,我们可以管理多个,请注意进入和退出的顺序。

with Cat('Tom') as tom, Cat('Harry') as harry:
tom.hello()
harry.hello() enter from Cat named Tom
enter from Cat named Harry
hello, Tom
hello, Harry
exit from Cat named Harry
exit from Cat named Tom

3、contextmanager

可能你还是觉得实现__enter__和__exit__很麻烦。python提供了contextlib.contextmanager

让我们重写上面的例子,使用contextmanager

from contextlib import contextmanager as _contextmanager

@_contextmanager
def cat(name):
print 'enter cat named %s' % name
yield name
print 'exit cat named %s' % name

执行,并打印结果

with cat('Kitty') as kitty:
print 'hello, %s' % kitty enter cat named Kitty
hello, Kitty
exit cat named Kitty

as后面的实例,是通过yield语句返回的。这里是返回了一个字符串。

当然,同样支持管理多个实例

with cat('Kitty') as kitty, cat('Tom') as tom:
print 'hello, %s' % kitty
print 'hello, %s' % tom enter cat named Kitty
enter cat named Tom
hello, Kitty
hello, Tom
exit cat named Tom
exit cat named Kitty

4、最后给出一个实例

使用上下文管理器实现redis分布式锁

# -*- coding:utf-8 -*-
from __future__ import print_function
import redis
import time
import multiprocessing
from contextlib import contextmanager as _contextmanager
# 简单创建redis的客户端
r = redis.Redis(host='localhost', port=6379, db=0) # 分布式锁实现
# finally中验证本线程是否获得锁, 是为了防止误删别的线程获取的锁
@_contextmanager
def dist_lock(client, key):
dist_lock_key = 'lock:%s' % key
is_acquire_lock = False
try:
is_acquire_lock = _acquire_lock(client, dist_lock_key)
yield
finally:
if is_acquire_lock:
_release_lock(client, dist_lock_key) # 尝试获取锁
# 成功: 返回True, 失败: 抛出异常
# 使用set nx ex原语, 使得setnx和expire操作成为原子操作
def _acquire_lock(client, key):
is_lock = r.set(key, 1, nx=True, ex=10)
if not is_lock:
raise Exception("already locked!")
return is_lock # 释放锁
# 简单删除key
# 如果删除失败, 锁也会通过expire时间超时
def _release_lock(client, key):
client.delete(key) # 测试函数
# 获取锁成功, 打印成功, 并持有锁3s
# 获取锁失败, 直接打印
def func():
while 1:
try:
with dist_lock(r, 'key'):
print("*", end='')
time.sleep(3)
except Exception, ex:
print('!', end='') # 多进程启动
# 这种模式下, 线程锁无效, 可以验证分布式锁
process_list = list()
for i in range(2):
process_list.append(multiprocessing.Process(target=func))
for process in process_list:
process.start()
for process in process_list:
process.join()

python contextlib 上下文管理器的更多相关文章

  1. 谈一谈Python的上下文管理器

    经常在Python代码中看到with语句,仔细分析下,会发现这个with语句功能好强,可以自动关闭资源.这个在Python中叫上下文管理器Context Manager.那我们要怎么用它,什么时候用它 ...

  2. 【Python】 上下文管理器和contextlib

    上下文管理器 一直对python中的上下文管理比较迷惑,趁着今天研究SQLAlchemy顺便看了一下,感觉稍微清楚了一点.http://www.cnblogs.com/chenny7/p/421344 ...

  3. python 黑魔法 ---上下文管理器(contextor)

    所谓上下文 计算机上下文(Context)对于我而言,一直是一个很抽象的名词.就像形而上一样,经常听见有人说,但是无法和现实认知世界相结合. 最直观的上下文,莫过于小学的语文课,经常会问联系上下文,推 ...

  4. Python 的上下文管理器是怎么设计的?

    花下猫语:最近,我在看 Python 3.10 版本的更新内容时,发现有一个关于上下文管理器的小更新,然后,突然发现上下文管理器的设计 PEP 竟然还没人翻译过!于是,我断断续续花了两周时间,终于把这 ...

  5. python使用上下文管理器实现sqlite3事务机制

    如题,本文记录如何使用python上下文管理器的方式管理sqlite3的句柄创建和释放以及事务机制. 1.python上下文管理(with) python上下文管理(context),解决的是这样一类 ...

  6. (转)contextlib — 上下文管理器工具

    原文:https://pythoncaff.com/docs/pymotw/contextlib-context-manager-tool/95 这是一篇社区协同翻译的文章,你可以点击右边区块信息里的 ...

  7. python的上下文管理器-1

    reference:https://zhuanlan.zhihu.com/p/26487659 来看看如何正确关闭一个文件. 普通版: def m1(): f = open("output. ...

  8. contextlib 上下文管理器

    在Python中,读写文件这样的资源要特别注意,必须在使用完毕后正确关闭它们.正确关闭文件资源的一个方法是使用try...finally: try: f = open('/path/to/file', ...

  9. python的上下文管理器

    直接上代码: f = open('123.txt','w') try: f.write('hello world') except Exception: pass finally: f.close() ...

随机推荐

  1. Markdown(editormd)语法解析成html

    我们在一些网站中可以见到一款网页编辑器--markdown: 这是一款功能强大的富文本编辑器,之前自己在网页上使用的时候遇到了一点点的问题,现在跟大家分享下 在我们写了文章之后是需要将内容保存到数据库 ...

  2. KVM网页管理工具WebVirtMgr部署

    KVM-WebVirtMgr 0ther https://github.com/retspen/webvirtmgr/wiki System Optimization(Only CentOS6.X) ...

  3. 201521123090《JAVA程序设计》第二周学习总结

    1. 本章学习总结 java基本数据类型 String类对象使用 枚举类型及switch分支 容器的概念 2. 书面作业 Q1.使用Eclipse关联jdk源代码(截图),并查看String对象的源代 ...

  4. 201521123026 《Java程序设计》第一周学习总结

    1. 本章学习总结 1.简要了解JAVA的发展史以及其特点(面向对象.跨平台性,健壮性,安全性,可移植性,多线程性,动态性等) 2.认识JAVA三大平台(Java SE,Java EE,JavaME) ...

  5. 201521123088 《Java程序设计》第14周学习总结

    1. 本周学习总结 2. 书面作业 1. MySQL数据库基本操作建立数据库,将自己的姓名.学号作为一条记录插入.(截图,需出现自己的学号.姓名)在自己建立的数据库上执行常见SQL语句(截图) 2. ...

  6. latch session allocation

    应用反馈上午10点左右出现大量应用连接数据库报错 采集9点-10点和10点-11点的AWR报告进行分析 DB时间明显差异,再继续分析等待事件 可以看出有session相关的Latch等待事件,查看相关 ...

  7. js的原型

    在讲js的原型之前,必须先了解下Object和Function. Object和Function都作为JS的自带函数,Object继承自己,Funtion继承自己,Object和Function互相是 ...

  8. Android SDK Manager 闪退的解决办法

    (一)方案一 原理:  SDK Manager.exe 通过调用 android-sdk-windows\tools\lib\find_java.bat 确认  java.exe 的路径 启用 cmd ...

  9. 基于FPGA的腐蚀膨胀算法实现

    本篇文章我要写的是基于的腐蚀膨胀算法实现,腐蚀膨胀是形态学图像处理的基础,,腐蚀在二值图像的基础上做"收缩"或"细化"操作,膨胀在二值图像的基础上做" ...

  10. JVM菜鸟进阶高手之路三

    转载请注明原创出处,谢谢! 笨神大大分享: 小程序里面搜索:JVMPocket,这个小程序是笨神大大提供的,里面可以搜索相关JVM参数,用法. -XX:MaxTenuringThreshold,这个参 ...