Python等待x秒钟以获取按键,如果没有按下则继续执行。

12
我正在寻找一个能执行以下操作的代码片段/示例:
- 显示一条消息,如“按任意键进行配置,或等待X秒后继续” - 等待,例如,5秒后继续执行,或者如果按下了某个键,则进入configure()子程序。
5个回答

24
如果你使用Unix/Linux系统,那么select模块会对你有所帮助。
import sys
from select import select

print "Press any key to configure or wait 5 seconds..."
timeout = 5
rlist, wlist, xlist = select([sys.stdin], [], [], timeout)

if rlist:
    print "Config selected..."
else:
    print "Timed out..."

如果你使用的是Windows系统,那么可以查看msvcrt模块。(请注意,这在IDLE中不起作用,但在命令提示符中可以使用)
import sys, time, msvcrt

timeout = 5
startTime = time.time()
inp = None

print "Press any key to configure or wait 5 seconds... "
while True:
    if msvcrt.kbhit():
        inp = msvcrt.getch()
        break
    elif time.time() - startTime > timeout:
        break

if inp:
    print "Config selected..."
else:
    print "Timed out..."

确实是为Linux而设计的。谢谢! - friedkiwi
10
关于 Windows 部分:我强烈建议在 while 循环结束时插入 time.sleep(0.5),否则该进程在等待时会浪费相当多的处理器时间... - Alexander Tobias Bockstaller

2

Python没有标准方法可以捕获键盘输入,只能通过input()和raw_input()来获取。如果您真的想要这个功能,您可以使用Tkinter或pygame来捕获按键作为“事件”。还有一些特定于平台的解决方案,如pyHook。但是,如果您的程序不绝对需要这个功能,我建议您以其他方式解决问题。


2
如果您结合使用time.sleep、threading.Thread和sys.stdin.read,就可以轻松地等待指定的时间段以获取输入,然后继续执行。
t = threading.Thread(target=sys.stdin.read(1) args=(1,))
t.start()
time.sleep(5)
t.join()

1

这是我如何完成它的:

import threading
import time
import sys


class MyThread(threading.Thread):
    def __init__(self, threadID, name, counter, f):
        super().__init__()
        self.threadID = threadID
        self.name = name
        self.counter = counter
        self.func = f

    def run(self):
        self.func()

class KeyboardMonitor:
    def __init__(self):
        # Setting a boolean flag is atomic in Python.
        # It's hard to imagine a boolean being 
        # anything else, with or without the GIL.
        # If inter-thread communication is anything more complicated than
        # a couple of flags, you should replace low level variables with 
        # a thread safe buffer.
        self.keepGoing = True

    def wait4KeyEntry(self):
        while self.keepGoing:
            s = input("Type q to quit: ")
            if s == "q":
                self.keepGoing = False

    def mainThread(self, f, *args, **kwargs):
        """Pass in some main function you want to run, and this will run it
        until keepGoing = False. The first argument of function f must be 
        this class, so that that function can check the keepGoing flag and 
        quit when keepGoing is false."""
        keyboardThread = MyThread(1, "keyboard_thread", 0, self.wait4KeyEntry)
        keyboardThread.start()
        while self.keepGoing:
            f(self, *args, **kwargs)

def main(keyMonitorInst, *args, **kwargs):
    while keyMonitorInst.keepGoing:
        print("Running again...")
        time.sleep(1)

if __name__ == "__main__":
    uut = KeyboardMonitor()
    uut.mainThread(main)

与其使阻塞调用超时,我的方法是启动一个线程等待用户输入,而另一个线程则执行其他操作。这两个进程通过一小部分原子操作进行通信:在这种情况下,设置一个布尔标志。对于比原子操作更复杂的任何事情,显然你应该使用线程安全的缓冲区替换原子变量。

0

基于https://note.nkmk.me/en/python-while-usage/的想法和其他来源。

如果在5秒内按下CTRL-C,程序将停止,否则将继续运行。

适用于Python 3,不需要任何外部(pip install ...)库。

应该适用于Linux和Windows。

如果您希望程序更频繁地检查用户输入,请在time.sleep()之前注释掉print函数,并将time.sleep(1)更改为time.sleep(0.1)。您可能还会使用顶部的print函数。

import time

def fn_wait_for_user_input(seconds_to_wait,message):
    #print('waiting for',seconds_to_wait, 'seconds ...' )
    print (message, seconds_to_wait)
    start_time = time.time()
    try:
        while (time.time() - start_time ) < seconds_to_wait:
            '''
            parenthesis, from inside out:
            time.time() which is current time    - start time, if it is more than 10 seconds, time's up :)
            int ; so we don't count 10 -1,02=8; instead we will count 10-1 = 9, meaning 9 seconds remaining, not 8
            seconds to wait - everything else ; so we get reverse count from 10 to 1, not from 1 to 10
            '''
            print("%d" %  (  seconds_to_wait -   int(  (time.time() - start_time )   )    )    ) 
            time.sleep(1)
        print('No keypress detected.')
        return 1 #no interrupt after x seconds
    except KeyboardInterrupt:
        print('Keypress detected - exiting.')
        return 0 #interrupted
        
    


if fn_wait_for_user_input(5, "program will continue if you don't press CTRL-C within seconds:" )  == 1:
    print('continuing ....')
else:
    print('not continuing.')




注意:
使用此方法将所有内容打印在一行中:
print("%d" %  (  seconds_to_wait -   int(  (time.time() - start_time )   )    ), end=' ', flush=True   ) #needs flush inside loop...buffered

使用这个来在函数内继续执行:
if fn_wait_for_user_input(5, "program will continue if you don't press CTRL-C within seconds:" )  == 1:
    #print('continuing ....')
    pass
else:
    #print('not continuing.')
    #exit function
    return


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接