python使用比with更优雅的contextlib实现上下文

前几天发现了一个优化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-8
class 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
  
@contextmanager
def 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 contextmanager
from random import random

DEFAULT_EXPIRES = 15
DEFAULT_RETRIES = 5

@contextmanager
def 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都是随你的便的,如果想提高你的逼格,倒是真的可以试试。 


大家觉得文章对你有些作用! 如果想赏钱,可以用微信扫描下面的二维码,感谢!
另外再次标注博客原地址  xiaorui.cc

5 Responses

  1. Yuan_SU 2016年11月24日 / 下午2:52

    这个分布式锁有问题嘛?get_stored = client.get(key) 的时候返回false,此后别的进程stored = client.set(key, 1)了,是会出错吗?

  2. (^o^)/~ 2016年11月4日 / 下午10:31

  3. h3l 2015年5月14日 / 下午3:24

    楼主好巧 我自己写经常写nima

  4. 奋战 2014年12月25日 / 上午7:29

    不错不错

发表评论

邮箱地址不会被公开。 必填项已用*标注