我几乎解决了这个问题,但我认为我需要朝着正确的方向努力。
我希望每五秒钟做一次,直到 经过一段时间或用户中断它(在这种情况下,它完成了循环的迭代)在完成之前)。
import time
import threading
def do_something():
T0 = time.clock()
while (time.clock() - T0) < 60 and not e.isSet(): #as long as 60s haven't elapsed
#and the flag is not set
#here do a bunch of stuff
time.sleep(5)
thread = threading.Thread(target=do_something, args=())
thread.start()
e = threading.Event()
while thread.isAlive():
#here I want the main thread to wait for a keypress and, if it receives it,
#set the event e, which will cause the thread to finish its work.
我无法弄清楚如何使最后一行工作。在循环内使用raw_input()
将阻塞,直到用户点击输入线程是否完成其工作。还有另一个模块可以做我想要的吗?
编辑:我使用的是Windows XP。
答案 0 :(得分:2)
您可以使用thread.interrupt_main()
。
示例:强>
import thread
import time
import threading
e = threading.Event()
def main():
thread.start_new_thread(wait_for_input, tuple())
thread.start_new_thread(do_something, tuple())
def wait_for_input():
raw_input()
e.set()
def do_something():
T0 = time.clock()
while (time.clock() - T0) < 60 and not e.isSet(): #as long as 60s haven't elapsed
#and the flag is not set
#here do a bunch of stuff
time.sleep(5)
thread.interrupt_main() # kill the raw_input thread
try:
thread.start_new_thread(main, tuple())
while 1:
time.sleep(0.1)
except KeyboardInterrupt:
pass
答案 1 :(得分:2)
以下是我解决问题的方法。我真的不想转移到较低级别的thread
模块,我觉得我很高兴用户使用CTRL-C来使程序正常退出。
由于它重新定位KeyboardInterrupt
的方式,这有点像一个小讽,这意味着它无法真正嵌入到所需的代码中需要CTRL-C成为一个不合适的退出。但是我的目的没问题。
import time
import threading
def do_something():
T0 = time.clock()
while (time.clock() - T0) < 60 and not e.isSet(): #as long as 60s haven't elapsed
#and the flag is not set
#here do a bunch of stuff
time.sleep(5)
thread = threading.Thread(target=do_something, args=())
e = threading.Event()
thread.start()
print 'Press CTRL-C to interrupt'
while thread.isAlive():
try: time.sleep(1) #wait 1 second, then go back and ask if thread is still alive
except KeyboardInterrupt: #if ctrl-C is pressed within that second,
#catch the KeyboardInterrupt exception
e.set() #set the flag that will kill the thread when it has finished
print 'Exiting...'
thread.join() #wait for the thread to finish
更新:事实证明使用GUI按钮要简单得多。以下代码不涉及KeyboardInterrupt
。
import time
import threading
import Tkinter as Tk
def do_something():
T0 = time.clock()
while (time.clock() - T0) < 60 and not e.isSet(): #as long as 60s haven't elapsed
#and the flag is not set
#here do a bunch of stuff
time.sleep(5)
def _quit():
print 'Exiting...'
e.set()
thread.join() #wait for the thread to finish
root.quit()
root.destroy()
root = Tk.Tk()
QuitButton = Tk.Button(master=root, text='Quit', command=_quit) #the quit button
QuitButton.pack(side=Tk.BOTTOM)
thread = threading.Thread(target=do_something, args=())
e = threading.Event()
thread.start()
root.mainloop()
答案 2 :(得分:1)
注意:我在您提到使用Windows XP之前写过这个答案,因此它无法帮助您 - select
only works on sockets under Windows。我认为答案对其他人来说仍然有用,所以我会留在这里。
这比编写示例代码要复杂得多,因为我确定它需要一些调试,但我可能会这样解决问题:
我在循环中使用select
,等待sys.stdin
,超时为5秒。每次返回时,如果没有输入,我会再次启动线程(可能检查最后一个线程是否已经完成运行),然后继续循环。如果输入存在,我将退出循环。
当select
表示存在输入时,我可以将其视为输入中的中断或read
,并评估它是否构成有效中断 - 如果不是,我可以缓冲它等待进一步输入以完成中断。如果是中断,我会等待线程完成工作。