Python中有没有一种简单的方法可以等待特定条件为真?

Python中有没有一种简单的方法可以等待特定条件为真?,python,Python,我需要在脚本中等待一定数量的条件变为真 我知道我可以使用条件变量和朋友来滚动自己的事件,但是我不想经历所有的麻烦,因为一些对象属性的变化来自包裹的C++库(Boosi.python)中的外部线程,所以我不能只在类中劫持它让我要么尝试创建和发出一个来自C++的Python条件变量,要么包装一个本地变量,并在Python上等待,这两个都听起来很不必要,复杂和无聊。 有没有一种更简单的方法,除非对条件进行连续轮询 理想情况下,它将沿着 res = wait_until(lambda: some_pre

我需要在脚本中等待一定数量的条件变为真

我知道我可以使用条件变量和朋友来滚动自己的事件,但是我不想经历所有的麻烦,因为一些对象属性的变化来自包裹的C++库(Boosi.python)中的外部线程,所以我不能只在类中劫持<代码>它让我要么尝试创建和发出一个来自C++的Python条件变量,要么包装一个本地变量,并在Python上等待,这两个都听起来很不必要,复杂和无聊。 有没有一种更简单的方法,除非对条件进行连续轮询

理想情况下,它将沿着

res = wait_until(lambda: some_predicate, timeout)
if (not res):
    print 'timed out'

你基本上回答了你自己的问题:没有


由于您在boost.python中处理外部库,这些库可能会在空闲时更改对象,因此您需要让这些例程调用事件处理程序刷新,或者使用条件

不幸的是,满足您的限制的唯一可能性是定期投票,例如

import time

def wait_until(somepredicate, timeout, period=0.25, *args, **kwargs):
  mustend = time.time() + timeout
  while time.time() < mustend:
    if somepredicate(*args, **kwargs): return True
    time.sleep(period)
  return False
导入时间
def wait_until(somepredicate,timeout,period=0.25,*args,**kwargs):
mustend=time.time()+超时
while time.time()

等等。如果
somepredicate
可以分解(例如,如果已知它是多个子句的
,特别是如果其中一些子句通过
线程化.Event
s或任何其他方式被检测到,从而受到优化,则可以通过多种方式对其进行优化),但在您要求的一般术语中,这种低效的方法是唯一的出路。

以下是Alex解决方案的线程扩展:

import time
import threading

# based on https://stackoverflow.com/a/2785908/1056345                                                                                                                                                                                                                                                                         
def wait_until(somepredicate, timeout, period=0.25, *args, **kwargs):
    must_end = time.time() + timeout
    while time.time() < must_end:
        if somepredicate(*args, **kwargs):
            return True
        time.sleep(period)
    return False

def wait_until_par(*args, **kwargs):
    t = threading.Thread(target=wait_until, args=args, kwargs=kwargs)
    t.start()
    print ('wait_until_par exits, thread runs in background')

def test():
    print('test')

wait_until_par(test, 5)
def wait_until(delegate, timeout: int):
end = time.time() + timeout
while time.time() < end:
    if delegate():
        return True
    else:
        time.sleep(0.1)
return False
导入时间
导入线程
#基于https://stackoverflow.com/a/2785908/1056345                                                                                                                                                                                                                                                                         
def wait_until(somepredicate,timeout,period=0.25,*args,**kwargs):
必须结束=time.time()+超时
while time.time()必须结束:
如果somepredicate(*args,**kwargs):
返回真值
时间。睡眠(周期)
返回错误
def等待直到参数(*args,**kwargs):
线程(目标=等待,args=args,kwargs=kwargs)
t、 开始()
打印('等待\u直到\u par退出,线程在后台运行')
def test():
打印(‘测试’)
等待,直到达到标准(测试,5)
这对我很有效

direction = ''
t = 0
while direction == '' and t <= 1:
    sleep(0.1)
    t += 0.1
direction=''
t=0
而方向==''和t建议的解决方案:

import time
import threading

# based on https://stackoverflow.com/a/2785908/1056345                                                                                                                                                                                                                                                                         
def wait_until(somepredicate, timeout, period=0.25, *args, **kwargs):
    must_end = time.time() + timeout
    while time.time() < must_end:
        if somepredicate(*args, **kwargs):
            return True
        time.sleep(period)
    return False

def wait_until_par(*args, **kwargs):
    t = threading.Thread(target=wait_until, args=args, kwargs=kwargs)
    t.start()
    print ('wait_until_par exits, thread runs in background')

def test():
    print('test')

wait_until_par(test, 5)
def wait_until(delegate, timeout: int):
end = time.time() + timeout
while time.time() < end:
    if delegate():
        return True
    else:
        time.sleep(0.1)
return False

另一个不错的软件包是等待
-

安装:

pip install waiting
用法: 您可以传递一个函数,该函数将在每次调用时作为一个条件、一个超时,并且(这很有用)您可以传递等待的描述,如果您得到TimeoutError,将显示该描述

使用函数:

from waiting import wait


def is_something_ready(something):
    if something.ready():
        return True
    return False


# wait for something to be ready
something = # whatever

wait(lambda: is_something_ready(something), timeout_seconds=120, waiting_for="something to be ready")

# this code will only execute after "something" is ready
print("Done")


注意:等待结束时,函数必须返回布尔值-True,否则返回False

import time
def no() :
    if (Condition !!!) :
        it got true
        oh()
    else:
        time.sleep(1) /Don't remove or don't blame me if ur system gets ""DEAD""
        no()
def oh() :   /Ur main program 
    while True:
        if(bla) :
            .......
            no()
        else :
            time.sleep(1)
            oh()

oh()

希望能有所帮助这里有另一个解决方案。目标是让线程在以非常精确的顺序执行某些工作之前互相等待。这项工作可能需要未知的时间。持续轮询不好有两个原因:它占用CPU时间,并且在满足条件后操作不会立即启动

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()
以及测试它的方法

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)
用于多处理的服务生:

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()

如果这仍然不是最佳解决方案,请发表意见。

从计算角度来看,必须在某个地方、某个时间检查所有条件。如果有两部分代码,一部分生成条件更改,另一部分在某些条件更改为真时应执行,则可以执行以下操作:

在主线程中有更改条件的代码,在工作线程中有当某些条件为真时应启动的代码

from threading import Thread,Event

locker = Event()

def WhenSomeTrue(locker):
    locker.clear() # To prevent looping, see manual, link below
    locker.wait(2.0) # Suspend the thread until woken up, or 2s timeout is reached
    if not locker.is_set(): # when is_set() false, means timeout was reached
        print('TIMEOUT')
    else:
    #
    # Code when some conditions are true
    #
worker_thread = Thread(target=WhenSomeTrue, args=(locker,))
worker_thread.start()

cond1 = False
cond2 = False
cond3 = False

def evaluate():
    true_conditions = 0

    for i in range(1,4):
        if globals()["cond"+str(i)]: #access a global condition variable one by one
            true_conditions += 1     #increment at each true value
    if true_conditions > 1:
        locker.set() # Resume the worker thread executing the else branch
    #Or just if true_conditions > 1: locker.set();
    #true_conditions would need be incremented when 'True' is written to any of those variables

#
# some condition change code
#
evaluate()

有关此方法的更多信息,请访问:

,我最后就是这么做的。幸运的是,性能不是一个问题(这是一个测试脚本)。可能还有另一个解决方案。即使在2018年,也没有办法做到这一点吗?在中记录的“.waitvariable”通用小部件方法可能会为此做一些小技巧。我不知道事件,
set()
wait()
。最终在我的代码中使用了这种类型的模式。肯定比
sleep()更优雅。
wait函数应该使用passtimeout\u秒来代替超时