10

我几乎解决了这个问题,但我认为我需要朝着正确的方向轻推。

我想每五秒做一次,直到经过一定时间用户中断它(在这种情况下,它在完成之前完成循环的迭代)。

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。

4

3 回答 3

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 
于 2012-08-01T12:45:35.307 回答
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()
于 2012-08-01T13:31:44.597 回答
1

注意:在您提到您使用的是 Windows XP 之前,我已经写了这个答案,因此它对您没有帮助-<a href="http://docs.python.org/library/select.html#module- select" rel="nofollow">select仅适用于 Windows 下的套接字。我认为答案对其他人仍然有用,所以我将其留在这里。


这比我编写示例代码要复杂一些,因为我确信它需要一些调试,但我可能会这样解决问题:

我会select在一个循环中使用,等待sys.stdin5 秒超时。每次它返回时,如果没有输入,我会再次启动线程(也许检查最后一个线程是否真正完成运行),然后继续循环。如果存在输入,我将退出循环。

select指示存在输入时,我可以将其视为完全中断或read在输入中,并评估它是否构成有效中断——如果不是,我可以将其缓冲等待进一步的输入以完成中断。如果是中断,我会等待线程完成工作。

于 2012-08-01T12:09:22.290 回答