Python—执行某些操作直到按键或超时



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

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

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,并推测它是否构成有效中断——如果不是,我可以缓冲它,等待进一步的输入以完成中断。如果是中断,我会等待线程完成工作。

相关内容

  • 没有找到相关文章

最新更新