How to wait for 20 secs for user to press any key?
Asked Answered
J

3

5

How can I wait for user to press any key for 20 secs? I.e. I show the message and it counts 20 secs, the code continues execution either if 20 secs are passed OR if user pressed any key. How can I do it with python?

Jaguarundi answered 2/8, 2012 at 18:51 Comment(5)
Look up non-blocking input, then implement that in a while loop that checks the current time compared to the starting time.Playhouse
@Lanaru: why a while loop? Sounds like a bad case of busy-waiting. Something like select() with a timeout could do the same thing.Buchan
press any key is not equal input any stringKildare
I did see a cross-platform answer using pygame.. but there has to be a better way.Tejeda
possible duplicate of Keyboard input with timeout in PythonAldarcie
K
7

If you're on Windows:

def wait_for_user(secs):
    import msvcrt
    import time
    start = time.time()
    while True:
        if msvcrt.kbhit():
            msvcrt.getch()
            break
        if time.time() - start > secs:
            break
Kopeck answered 2/8, 2012 at 19:15 Comment(1)
It's a little petty, but if someone hits a character during the sleep, you're waiting for no reason. Best to compare the time rather than sleep.Tejeda
P
2

One possible solution is to use select to check the values, but I don't like it, I feel like I'm wasting my time.
On the other hand you can use signaling on Linux systems to handle the problem. after a certain amount of time, a exception will be raised, try fails and code continues in except :

import signal

class AlarmException(Exception):
    pass

def alarmHandler(signum, frame):
    raise AlarmException

def nonBlockingRawInput(prompt='', timeout=20):
    signal.signal(signal.SIGALRM, alarmHandler)
    signal.alarm(timeout)
    try:
        text = raw_input(prompt)
        signal.alarm(0)
        return text
    except AlarmException:
        print '\nPrompt timeout. Continuing...'
    signal.signal(signal.SIGALRM, signal.SIG_IGN)
    return ''

The code has been taken from here

Prefecture answered 2/8, 2012 at 19:26 Comment(1)
Also in your special case it has another pitfall which is raw_input waits for you to enter \n at end, because Python is in line buffered mode by default.Prefecture
B
0

(Warning: untested code)

Something like:

 import sys
 import select

 rlist, _, _ = select.select([sys.stdin], [], [], timeout=20)
 if len(rlist) == 0:
     print "user didnt input anything within 20 secs"
 else:
     print "user input something within 20 secs. Now you just have to read it"

edit see: http://docs.python.org/library/select.html

Buchan answered 2/8, 2012 at 19:17 Comment(2)
I didn't know about the select module, that's good to know about. I just tested it on windows, and it didn't work. From the docs: Note: File objects on Windows are not acceptable, but sockets are. On Windows, the underlying select() function is provided by the WinSock library, and does not handle file descriptors that don’t originate from WinSock.Kopeck
@BrendenBrown: Wow, I had no idea. Thank you for the update (this furthers my confusion at Windows development ...)Buchan

© 2022 - 2024 — McMap. All rights reserved.