开发者

Python wait x secs for a key and continue execution if not pressed

I'm a n00b to 开发者_StackOverflow社区python, and I'm looking a code snippet/sample which performs the following:

  • Display a message like "Press any key to configure or wait X seconds to continue"
  • Wait, for example, 5 seconds and continue execution, or enter a configure() subroutine if a key is pressed.

Thank you for your help!

Yvan Janssens


If you're on Unix/Linux then the select module will help you.

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..."

If you're on Windows, then look into the msvcrt module. (Note this doesn't work in IDLE, but will in cmd prompt)

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..."

Edit Changed the code samples so you could tell whether there was a timeout or a keypress...


Python doesn't have any standard way to catch this, it gets keyboard input only through input() and raw_input().

If you really want this you could use Tkinter or pygame to catch the keystrokes as "events". There are also some platform-specific solutions like pyHook. But if it's not absolutely vital to your program, I suggest you make it work another way.


If you combine time.sleep, threading.Thread, and sys.stdin.read you can easily wait for a specified amount of time for input and then continue.

t = threading.Thread(target=sys.stdin.read(1) args=(1,))
t.start()
time.sleep(5)
t.join()


Here's how I did it:

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)

Rather than make a blocking call time out, my approach is to start a thread that waits for the user to enter input, while another thread does something else. The two processes communicate through a small number of atomic operations: in this case, setting a boolean flag. For anything more complicated than atomic operations, obviously you should replace the atomic variable with a threadsafe buffer of some kind.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜