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秒来代替超时