From StackOverflow: http://stackoverflow.com/questions/1335507/keyboard-input-with-timeout-in-python
This seems to be something folks want to do. I recently had an interest to launch a script every morning to have me check in with some goal, and was wondering how I could do this, i.e.
At 7:00 AM, fire up a script with some prompt and input request, something like:
raw_input("Time to log the daily weight-in! How much today? ")
But… suppose I slept in today. The prompt just sits there, blocking… and suppose the script that launches this inquiry now fires up a new instance of the program… will that prompt and wait, too? Ugh.
Better to have something that operates like “oh look, there’s been no answer for the past 30 minutes, maybe he forgot or slept in?” and then concludes “okay, log that there was no answer for today, and exit.” Simple, and no more stacked up instances.
Problem is, there’s apparently no read with timeout in Python. Or at least, not one that works, cross-platform. (There are some solutions with Linux signals.)
I found the following code at the above StackOverflow post mentioned above. It was downvoted, but I actually found this approach interesting, a kind of “out of the box” thinking approach to the problem. Here, a timer is set up. And what you do is indicate, via Ctrl-C, when you’re at the keyboard and ready to begin input. If the interrupt is never received? Then it’s a timeout.
Sure, it’s a little quirky, but it can get a job done.
Two things I discovered or realized:
- Of course, if you do start typing, and then walk away, it will block just like the original case.
- I tried changing the sleep loop to just a single sleep statement. But guess what — my Ctrl-C would not interrupt the sleep statement! (I”m on a Mac, fyi.) If you have a loop around the sleep, it can detect the interrupt in-between the sleep statement.
(I suppose I should head to the documentation to read up on this and verify my theory.) - If you press Ctrl-C, you may have a perceptible momentary wait, while the “sleep(1)” completes.
P.S. Here is the exact code by “try” from the StackOverflow post.
from time import sleep
print('Please provide input in 20 seconds! (Hit Ctrl-C to start)')
try:
for i in range(0,20):
sleep(1) # could use a backward counter to be preeety :)
print('No input is given.')
except KeyboardInterrupt:
raw_input('Input x:')
print('You, you! You know something.')
Here’s my slightly modified version, as a function (to make it easier to test in IDLE).
And sorry for the wrapping… i’m looking for a new template for the blog.
def prompt_with_timeout():
from time import sleep
print('Waiting... please press Ctrl-C when you wish to proceed.')
try:
for i in range(0, 30*60): # 30 minutes is 30*60 seconds
sleep(1)
print("Oops, sorry, no input was received today. Come back tomorrow.")
except KeyboardInterrupt:
weight_today = raw_input("Time to log the daily weight-in! How much today? ")
print ("Thanks for logging: " + weight_today)
return