1

Python3: I'm trying to allow a user a given amount of time to enter a response into an input, but after a given amount of time if they haven't entered anything, I want to abort the input and assign a default value to the variable that is storing the input, or otherwise feed default values into the input statement after the given time period.

I've tried this:

from threading import Timer
timeout = 2
t = Timer(timeout, print, ["\nSorry, time is up"])
t.start()
answer = input("You have 2 seconds to answer:")
t.cancel()
print(answer)

from a different stack overflow post, but the problem is that the interpreter still prompts the user for input even after the final line is executed and answer is printed, and this won't work for what I'm trying to do (essentially, a command line game that needs to keep going when the player isn't giving it input but update when it does receive input).

What is the best way to do this? I know python doesn't really have a timeout function or something like that, but is there any way to achieve this via system commands or a module?

2 Answers2

0

There are several plausible approaches (some of which are probably Unix-specific):

  1. Read the input in a subprocess that can be killed after the timeout. (Many functions, including subprocess.run, accept a timeout parameter to automate this.)
  2. Use alarm or similar to send your own process a signal (and install a signal handler that throws an exception).
  3. Have another thread close the descriptor being read after the timeout; this sounds drastic but is generally said to work, so long as you don’t accidentally open a file on the closed descriptor before restoring it with dup2.
  4. Read the input with lower-level facilities like non-blocking read and select—which will unfortunately disable nice things like readline.

In any case, you have to decide what to do with incomplete but non-empty input entered before the timeout. The terminal driver will likely transfer it invisibly to the next input prompt by default.

Davis Herring
  • 36,443
  • 4
  • 48
  • 76
0

Using a select call may be a easier way.

import sys, select

print "You have ten seconds to answer!"

i, o, e = select.select( [sys.stdin], [], [], 10 )

if (i):
  print "You said", sys.stdin.readline().strip()
else:
  print "You said nothing!"

Refer to Keyboard input with timeout?

Song Bi
  • 729
  • 1
  • 7
  • 11