Is there an easy way in Python to wait until certain condition is true?

后端 未结 8 1326

I need to wait in a script until a certain number of conditions become true?

I know I can roll my own eventing using condition variables and friends, but I don\'t wa

8条回答
  •  野趣味
    野趣味 (楼主)
    2020-12-23 21:17

    Here is another solution. The goal was to make threads to wait on each other before doing some work in a very precise order. The work can take unknown amount of time. Constant polling is not good for two reasons: it eats CPU time and action does not start immediately after condition is met.

    class Waiter():
    
        def __init__(self, init_value):
            self.var = init_value
            self.var_mutex = threading.Lock()
            self.var_event = threading.Event()
    
        def WaitUntil(self, v):
            while True:
                self.var_mutex.acquire()
                if self.var == v:
                    self.var_mutex.release()
                    return # Done waiting
                self.var_mutex.release()
                self.var_event.wait(1) # Wait 1 sec
    
        def Set(self, v):
            self.var_mutex.acquire()
            self.var = v
            self.var_mutex.release()
            self.var_event.set() # In case someone is waiting
            self.var_event.clear()
    

    And the way to test it

    class TestWaiter():
    
        def __init__(self):
            self.waiter = Waiter(0)
            threading.Thread(name='Thread0', target=self.Thread0).start()
            threading.Thread(name='Thread1', target=self.Thread1).start()
            threading.Thread(name='Thread2', target=self.Thread2).start()
    
        def Thread0(self):
            while True:
                self.waiter.WaitUntil(0)
                # Do some work
                time.sleep(np.random.rand()*2)
                self.waiter.Set(1)
    
        def Thread1(self):
            while True:
                self.waiter.WaitUntil(1)
                # Do some work
                time.sleep(np.random.rand())
                self.waiter.Set(2)
    
        def Thread2(self):
            while True:
                self.waiter.WaitUntil(2)
                # Do some work
                time.sleep(np.random.rand()/10)
                self.waiter.Set(0)
    

    Waiter for multiprocessing:

    import multiprocessing as mp
    import ctypes
    
    class WaiterMP():
        def __init__(self, init_value, stop_value=-1):
            self.var = mp.Value(ctypes.c_int, init_value)
            self.stop_value = stop_value
            self.event = mp.Event()
    
        def Terminate(self):
            self.Set(self.stop_value)
    
        def Restart(self):
            self.var.value = self.init_value
    
        def WaitUntil(self, v):
            while True:
                if self.var.value == v or self.var.value == self.stop_value:
                    return
                # Wait 1 sec and check aiagn (in case event was missed)
                self.event.wait(1)
    
        def Set(self, v):
            exit = self.var.value == self.stop_value
            if not exit: # Do not set var if threads are exiting
                self.var.value = v
            self.event.set() # In case someone is waiting
            self.event.clear()
    

    Please comment if this is still not the best solution.

提交回复
热议问题