我几乎已经解决了这个问题,但我认为我需要朝着正确的方向前进。
我想每五秒钟做一次,直到过了一定的时间或用户中断它(在这种情况下,它在完成之前完成了循环的迭代)。
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。
您可以使用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
以下是我解决问题的方法。我真的不想转到较低级别的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
Update:事实证明,使用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()
注意:在您提到您使用Windows XP之前,我已经写了这个答案,因此它对您没有帮助——select
只适用于Windows下的套接字。不过,我认为这个答案对其他人仍然有用,所以我就把它留在这里。
这比我喜欢写示例代码要复杂一些,因为我确信这需要一些调试,但我可能会这样处理问题:
我会在循环中使用select
,等待sys.stdin
,超时5秒。每次它返回时,如果没有输入,我会再次启动线程(也许是检查最后一个线程是否真的完成了运行),然后继续循环。如果有输入,我会退出循环。
当select
指示存在输入时,我可以直接将其视为一个完全中断或输入中的read
,并推测它是否构成有效中断——如果不是,我可以缓冲它,等待进一步的输入以完成中断。如果是中断,我会等待线程完成工作。