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

前端 未结 4 878
误落风尘
误落风尘 2020-12-09 20:31

I\'m a n00b to 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 secon
相关标签:
4条回答
  • 2020-12-09 21:15

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

    0 讨论(0)
  • 2020-12-09 21:16

    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.

    0 讨论(0)
  • 2020-12-09 21:22

    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 讨论(0)
  • 2020-12-09 21:30

    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()
    
    0 讨论(0)
提交回复
热议问题