我希望函数foo()
在一个线程中执行许多操作,并在等待期间定期检查另一个线程(主脚本)是否已将please_stop
变量设置为{{ 1}},在这种情况下,我希望True
立即返回一个值(例如foo()
)。
我最初的尝试看起来像这样:
False
它可以正常工作,但我发现import time
please_stop = False
def wait( n ) :
'''
Wait n seconds and return True, unless some other process
sets please_stop to True (and then return False).
'''
global please_stop
for t in range (n) :
if please_stop :
please_stop = False
return False
else :
print t
time.sleep(1)
return True
def foo() :
'''
Do a number of things, with wait() calls in between.
'''
global please_stop
print 'doing first thing'
if not wait( 5 ) : return False
print 'doing second thing'
if not wait( 5 ) : return False
print 'doing third thing'
return True
foo()
表达式非常笨重。实现此行为的最简单/最优雅的方法是什么,可能允许使用简单的if not wait( 5 ) : return False
表达式?我是否正在重新发明轮子,中断会不会在这里做得更好?
提前致谢。
答案 0 :(得分:0)
嗯,您可以使用threading.Event
而不是全局变量来简化wait
的实现:
import time
import threading
def wait(event, timeout):
if event.wait(timeout):
event.clear()
return False
else:
return True
def foo(event):
'''
Do a number of things, with wait() calls in between.
'''
print 'doing first thing'
if not wait(event, 5): return False
print 'doing second thing'
if not wait(event, 5): return False
print 'doing third thing'
return True
if __name__ == "__main__":
event = threading.Event()
t = threading.Thread(target=foo, args=(event,))
t.start()
time.sleep(6)
event.set()
输出:
doing first thing
doing second thing
但您仍在使用if not wait(5) : return False
模式。要摆脱这种情况,您需要在设置Event
时抛出异常。您可能不希望异常逃离foo
,因此您需要在try
正文周围使用except
/ foo
块,或者使用context manager:
import time
import threading
from contextlib import contextmanager
class Interrupt(Exception): pass
def wait(event, timeout):
if event.wait(timeout):
event.clear()
raise Interrupt()
else:
return True
@contextmanager
def interruptible():
try:
yield
except Interrupt:
pass
def foo(event):
'''
Do a number of things, with wait() calls in between.
'''
with interruptible():
print 'doing first thing'
wait(event, 5)
print 'doing second thing'
wait(event, 5)
print 'doing third thing'
return True
return False # This will only be reached the main thread interrupts foo
这与上一个示例的行为完全相同,唯一的区别是不是将False
返回到foo
,我们引发一个异常,它被上下文管理器捕获,但会导致我们跳过上下文中的其余代码。