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. Web颜色对照表大全

    Web上16种基本颜色名称 Name Hex (RGB) Red (RGB) Green (RGB) Blue (RGB) Hue (HSL/HSV) Satur. (HSL) Light (HSL) ...

  2. 201521123082 《Java程序设计》第12周学习总结

    201521123082 <Java程序设计>第12周学习总结 标签(空格分隔): java 1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结多流与文件相关内容. An ...

  3. 201521123098 《Java程序设计》 第5周学习总结

    1. 本周学习总结 1.1 尝试使用思维导图总结有关多态与接口的知识点. 1.2 可选:使用常规方法总结其他上课内容. 1. 对接口这一定义有了初步的了解: 2. 学习了如何定义实现类和如何实现一些接 ...

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

    1. 本周学习总结 2. 书面作业 1.注释的应用 使用类的注释与方法的注释为前面编写的类与方法进行注释,并在Eclipse中查看.(截图) 2.面向对象设计(大作业1,非常重要) 2.1 将在网上商 ...

  5. 201521123077 《Java程序设计》第10周学习总结

    1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结异常与多线程相关内容. 多线程 Runnable类 表示任务的类,可以当作参数传入Thread的构造器来运行该任务 Thread类 ...

  6. 201521123111《Java程序设计》第14周学习总结

    本次作业参考文件 MySql操作视频与数据库相关jar文件请参考QQ群文件. 1. 本周学习总结 1.1 以你喜欢的方式(思维导图.Onenote或其他)归纳总结多数据库相关内容. 连接数据库前,应先 ...

  7. Java课程设计 - 学生基本信息管理

    团队名称.团队成员介绍(需要有照片) 团队名称:此艺兴非彼艺兴 团队成员: 王兴:女,积极上进 曾艺佳:女,积极上进 项目git地址 StudentManage项目 项目git提交记录截图(要体现出每 ...

  8. Thrift教程初级篇——thrift安装环境变量配置第一个实例

    前言: 因为项目需要跨语言,c++客户端,web服务端,远程调用等需求,所以用到了RPC框架Thrift,刚开始有点虚,第一次接触RPC框架,后来没想到Thrift开发方便上手快,而且性能和稳定性也不 ...

  9. Python学习笔记004_字典_集合

    >>> # 字典 用大括号表示, 它是影射类型,相当于java中的Map >>> >>> dict1 = {'李宁': '一切皆有可能', '耐克 ...

  10. 自定义Django的中间件

    分析Django的生命周期,我们知道所有的http请求都要经过Django的中间件. 假如现在有一个需求,所有到达服务端的url请求都在系统中记录一条日志,该怎么做呢? Django的中间件的简介 D ...