Is there a python library for notification and waiting?
Asked Answered
K

2

6

I'm using python-zookeeper for locking, and I'm trying to figure out a way of getting the execution to wait for notification when it's watching a file, because zookeeper.exists() returns immediately, rather than blocking.

Basically, I have the code listed below, but I'm unsure of the best way to implement the notify() and wait_for_notification() functions. It could be done with os.kill() and signal.pause(), but I'm sure that's likely to cause problems if I later have multiple locks in one program - is there a specific Python library that is good for this sort of thing?

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
Kirchner answered 2/10, 2012 at 7:42 Comment(0)
P
11

The Condition variables from Python's threading module are probably a very good fit for what you're trying to do:

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

I've extended to the example to make it a little more obvious how you would adapt it for your purposes:

#!/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()
Pearliepearline answered 2/10, 2012 at 8:33 Comment(0)
A
0

My answer may not be relevant to your question, but it is relevant to the question title.

from threading import Thread,Event

locker = Event()

def MyJob(locker):
    while True:
        #
        # do some logic here
        #
        locker.clear() # Set event state to 'False'
        locker.wait() # suspend the thread until event state is 'True'

worker_thread = Thread(target=MyJob, args=(locker,))
worker_thread.start()

#
# some main thread logic here
#
locker.set() # This sets the event state to 'True' and thus it resumes the worker_thread

More information here: https://docs.python.org/3/library/threading.html#event-objects

Aureole answered 27/5, 2021 at 21:29 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.