前几天发现了一个优化with的模块contextlib,其实就是个封装。 那么首先说下,with是什么,玩python有半年经验的应该知道的。 这东西其实也没有什么太大的用处,只是隐藏的含有了一个关闭的逻辑,很像是try…finally…
这里标记下,原文链接是 xiaorui.cc
咱们用的os模块,读取文件的时候,其实他是含有__enter__ __exit__ 。 一个是with触发的时候,一个是退出的时候。
with file('nima,'r') as f: print f.readline()
那咱们自己再实现一个标准的可以with的类。 我个人写python的时候,喜欢针对一些需要有关闭逻辑的代码,构造成with的模式 。
#encoding:utf-8class echo: def __enter__(self): print 'enter' def __exit__(self,*args): print 'exit'with echo() as e: print 'nima'
contextlib是个比with优美的东西,也是提供上下文机制的模块,它是通过Generator装饰器实现的,不再是采用__enter__和__exit__。contextlib中的contextmanager作为装饰器来提供一种针对函数级别的上下文管理机制。
from contextlib import contextmanager@contextmanagerdef make_context() : print 'enter' try : yield {} except RuntimeError, err : print 'error' , err finally : print 'exit'with make_context() as value : print value
我这里再贴下我上次写的redis分布式锁代码中有关于contextlib的用法。其实乍一看,用了with和contextlib麻烦了,但是最少让你的主体代码更加鲜明了。
from contextlib import contextmanagerfrom random import randomDEFAULT_EXPIRES = 15DEFAULT_RETRIES = 5@contextmanagerdef dist_lock(key, client): key = 'lock_%s' % key try: _acquire_lock(key, client) yield finally: _release_lock(key, client)def _acquire_lock(key, client): for i in xrange(0, DEFAULT_RETRIES): get_stored = client.get(key) if get_stored: sleep_time = (((i+1)*random()) + 2**i) / 2.5 print 'Sleeipng for %s' % (sleep_time) time.sleep(sleep_time) else: stored = client.set(key, 1) client.expire(key,DEFAULT_EXPIRES) return raise Exception('Could not acquire lock for %s' % key)def _release_lock(key, client): client.delete(key)
用不用with或者是contextlib都是随你的便的,如果想提高你的逼格,倒是真的可以试试。
本文出自:http://blog.xiaorui.cc, 原文地址:http://xiaorui.cc/2014/12/21/%e4%bd%bf%e7%94%a8%e6%af%94with%e6%9b%b4%e4%bc%98%e9%9b%85%e7%9a%84contextlib%e5%ae%9e%e7%8e%b0%e4%b8%8a%e4%b8%8b%e6%96%87/, 感谢原作者分享。 当遗忘变成另一种开始,淡了回忆,痛最真实…