Keyboard Input With Timeout

Keyboard input with timeout?

The example you have linked to is wrong and the exception is actually occuring when calling alarm handler instead of when read blocks. Better try this:

import signal
TIMEOUT = 5 # number of seconds your want for timeout

def interrupted(signum, frame):
"called when read times out"
print 'interrupted!'
signal.signal(signal.SIGALRM, interrupted)

def input():
try:
print 'You have 5 seconds to type in your stuff...'
foo = raw_input()
return foo
except:
# timeout
return

# set alarm
signal.alarm(TIMEOUT)
s = input()
# disable the alarm after success
signal.alarm(0)
print 'You typed', s

Keyboard input timeout with visible countdown

To do this you need to move with cursor in the terminal depending on the operating system you are using, it is very tiring and it is not very solid to use the terminal in that way (a static stdout would be easier and safer), what I would do it is an output of this kind obviously you have to use a multithread programming to be able to use the file descriptor simultaneously


import time
import sys
import threading
import time
import sys


def get_input(t):
global stop_threads

while True:
input_cmd = input().lower()

if input_cmd == "yes" or input_cmd == "yup":
print("\n\nThanks script is now starting\n\n")
break
elif input_cmd == "no" or input_cmd == "nope":
print("\nOk as you wish, I'm stopping...\n")
break

stop_threads = True


def initial_startup(t):

print('Do you want to continue?')
t1 = threading.Thread(target=get_input, args=(t,), daemon=True)
t1.start()
while t:
global stop_timeout
global stop_threads

mins, secs = divmod(t, 60)
timer = '{:02d}:{:02d}'.format(mins, secs)

prompt = "You have %s time left... Answer yes or no only: " % timer
print(prompt)

sys.stdout.write("\x1b[1A") # cursor up one line
sys.stdout.write("\x1b[2K") # delete the last line

if stop_threads:
sys.exit(1)
time.sleep(1)

t -= 1

if timer == "00:01":
sys.stdout.write("\x1b[2K") # delete the last line
print("Timeout! try again")
sys.exit(1)


stop_threads = False
stop_timeout = False
t = 4
initial_startup(int(t))

Output

Do you want to continue?
You have 00:02 time left... Answer yes or no only:

Ok as you wish, I'm stopping...
Do you want to continue?
You have 00:02 time left... Answer yes or no only:
Timeout! try again
Do you want to continue?
You have 00:05 time left... Answer yes or no only:

Thanks script is now starting

How to set a timeout for Input

Doing the task you proposed isn't as easy as you might've guessed. It is easier to use the signal module to do this: (I have incorporated your code with a modified version of the answer I linked)

import signal, time

def TimedInput(prompt='', timeout=20, timeoutmsg = None):
def timeout_error(*_):
raise TimeoutError
signal.signal(signal.SIGALRM, timeout_error)
signal.alarm(timeout)
try:
answer = input(prompt)
signal.alarm(0)
return answer
except TimeoutError:
if timeoutmsg:
print(timeoutmsg)
signal.signal(signal.SIGALRM, signal.SIG_IGN)
return None

monsterhp = int(800)
y = 150
while monsterhp > 0:
timeout = 4
timeoutmsg = 'You ran out of time.'
print(" ")
prompt = "You have %d seconds Type 'attack' to hit the monster\nType here: " % timeout
answer = TimedInput(prompt, timeout, timeoutmsg)

if answer == "attack":
print("You strike the monster")
time.sleep(1)
monsterhp = monsterhp - y
print("War Lord Health:", monsterhp)

Note: this will only work on all unix/mac system

You can change your while loop to this, for a improved version of your code:)

while monsterhp > 0:
timeout = 4
timeoutmsg = 'You ran out of time.'
print(" ")
prompt = "You have %d seconds Type 'attack' to hit the monster\nType here: " % timeout
answer = TimedInput(prompt, timeout, timeoutmsg)

if answer == "attack":
print("You strike the monster")
time.sleep(1)
monsterhp = monsterhp - y
print("War Lord Health:", monsterhp)
elif answer == None:
print("The War Lord has killed you, you're now dead")
print("Thanks for playing, \nGAME OVER")
break

Skip the input function with timeout

You can use the inputimeout module

You can install the module by running cmd and typing this command

pip install inputimeout

You can use it like this

from inputimeout import inputimeout, TimeoutOccurred
try:
var = inputimeout(prompt='>>', timeout=5)
except TimeoutOccurred:
var = ''

Steps to use

  1. Import the module in file
  2. start the try method
  3. make a variable and instead of input use inputimeout function and enter values as prompt= and timeout=
  4. In except TimeoutOccurred: enter the value of the var if timeout is occured

Time-Limited Input?

Interesting problem, this seems to work:

import time
from threading import Thread

answer = None

def check():
time.sleep(2)
if answer != None:
return
print("Too Slow")

Thread(target = check).start()

answer = input("Input something: ")

python Keyboard input with timeout? getting error OSError: [WinError 10038] An operation was attempted on something that is not a socket

The solution I found is:

$ pip install inputimeout

from inputimeout import inputimeout, TimeoutOccurred
try:
something = inputimeout(prompt='>>', timeout=10)
except TimeoutOccurred:
something = 'Time is up'
print(something)

Timed user input in Python

You can use the Timer class for this purpose

from threading import Timer

timeout = 10
t = Timer(timeout, print, ['Sorry, times up!'])
t.start()
prompt = "You have %d seconds to answer the question. What color do cherries have?...\n" % timeout
answer = input(prompt)
t.cancel()

Output:

You have 10 seconds to answer the question. What color do cherries have?
(After 10 seconds)
Sorry, times up!


Related Topics



Leave a reply



Submit