2012-10-02 31 views
3

我正在使用python-zookeeper进行锁定,并且我试图找出一种让执行在观察文件时等待通知的方式,因为zookeeper.exists()立即返回而不是阻塞。是否有一个用于通知和等待的Python库?

基本上,我有下面列出的代码,但我不确定实现notify()wait_for_notification()函数的最佳方法。这可以通过os.kill()signal.pause()来完成,但是我相信如果我稍后在一个程序中有多个锁,可能会导致问题 - 是否有一个特定的Python库适合这种事情?

def get_lock(zh): 
    lockfile = zookeeper.create(zh,lockdir + '/guid-lock-','lock', [ZOO_OPEN_ACL_UNSAFE], zookeeper.EPHEMERAL | zookeeper.SEQUENCE) 

    while(True): 
     # this won't work for more than one waiting process, fix later 
     children = zookeeper.get_children(zh, lockdir) 
     if len(children) == 1 and children[0] == basename(lockfile): 
      return lockfile 

     # yeah, there's a problem here, I'll fix it later 
     for child in children: 
      if child < basename(lockfile): 
       break 

     # exists will call notify when the watched file changes 
     if zookeeper.exists(zh, lockdir + '/' + child, notify): 
      # Process should wait here until notify() wakes it 
      wait_for_notification() 


def drop_lock(zh,lockfile): 
    zookeeper.delete(zh,lockfile) 

def notify(zh, unknown1, unknown2, lockfile): 
    pass 

def wait_for_notification(): 
    pass 

回答

9

从Python的线程模块条件变量可能是一个非常适合你正在试图做什么:

http://docs.python.org/library/threading.html#condition-objects

我已经延伸到例如,使其一点点更明显你将如何适应你的目的:

#!/usr/bin/env python 

from collections import deque 
from threading import Thread,Condition 

QUEUE = deque() 

def an_item_is_available(): 
    return bool(QUEUE) 

def get_an_available_item(): 
    return QUEUE.popleft() 

def make_an_item_available(item): 
    QUEUE.append(item) 

def consume(cv): 
    cv.acquire() 
    while not an_item_is_available(): 
     cv.wait() 
    print 'We got an available item', get_an_available_item() 
    cv.release() 

def produce(cv): 
    cv.acquire() 
    make_an_item_available('an item to be processed') 
    cv.notify() 
    cv.release() 

def main(): 
    cv = Condition() 
    Thread(target=consume, args=(cv,)).start()  
    Thread(target=produce, args=(cv,)).start() 

if __name__ == '__main__': 
    main() 
+0

奇妙的是,这完美的做法。非常感谢! – paul88888