python - User input with a timeout, in a loop -
i'm trying create looping python function performs task , prompts user response , if user not respond in given time sequence repeat.
this loosely based off question: how set time limit on raw_input
the task represented some_function()
. timeout variable in seconds. have 2 problems following code:
the raw_input prompt not timeout after specified time of 4 seconds regardless of whether user prompts or not.
when raw_input of 'q' entered (without '' because know typed automatically entered string) function not exit loop.
`
import thread import threading time import sleep def raw_input_with_timeout(): prompt = "hello me you're looking for?" timeout = 4 astring = none some_function() timer = threading.timer(timeout, thread.interrupt_main) try: timer.start() astring = raw_input(prompt) except keyboardinterrupt: pass timer.cancel() if astring.lower() != 'q': raw_input_with_timeout() else: print "goodbye"
`
warning: intended work in *nix , osx requested not work in windows.
i've used this modification of activestate recipe basis code below. it's easy-to-use object can read input timeout. uses polling collect characters 1 @ time , emulate behavior of raw_input()
/ input()
.
input timeout
note: apparently _getch_nix()
method below doesn't work op me on osx 10.9.5. might have luck calling _getch_osx()
instead although seems work in 32-bit python since carbon doesn't support 64-bit.
import sys import time class timeoutinput(object): def __init__(self, poll_period=0.05): import sys, tty, termios # apparently timing of import important if using ide self.poll_period = poll_period def _getch_nix(self): import sys, tty, termios select import select fd = sys.stdin.fileno() old_settings = termios.tcgetattr(fd) try: tty.setraw(sys.stdin.fileno()) [i, o, e] = select([sys.stdin.fileno()], [], [], self.poll_period) if i: ch = sys.stdin.read(1) else: ch = '' finally: termios.tcsetattr(fd, termios.tcsadrain, old_settings) return ch def _getch_osx(self): # same discussion on original activestate recipe: # http://code.activestate.com/recipes/134892-getch-like-unbuffered-character-reading-from-stdin/#c2 import carbon if carbon.evt.eventavail(0x0008)[0] == 0: # 0x0008 keydownmask return '' else: # event contains following info: # (what,msg,when,where,mod)=carbon.evt.getnextevent(0x0008)[1] # # message (msg) contains ascii char # extracted 0x000000ff charcodemask; # number converted ascii character chr() , # returned (what,msg,when,where,mod)=carbon.evt.getnextevent(0x0008)[1] return chr(msg & 0x000000ff) def input(self, prompt=none, timeout=none, extend_timeout_with_input=true, require_enter_to_confirm=true): """timeout: float seconds or none (blocking)""" prompt = prompt or '' sys.stdout.write(prompt) # avoids couple of problems printing sys.stdout.flush() # make sure prompt appears before start waiting input input_chars = [] start_time = time.time() received_enter = false while (time.time() - start_time) < timeout: # keep polling characters c = self._getch_osx() # self.poll_period determines spin speed if c in ('\n', '\r'): received_enter = true break elif c: input_chars.append(c) sys.stdout.write(c) sys.stdout.flush() if extend_timeout_with_input: start_time = time.time() sys.stdout.write('\n') # consistency other "prints" sys.stdout.flush() captured_string = ''.join(input_chars) if require_enter_to_confirm: return_string = captured_string if received_enter else '' else: return_string = captured_string return return_string
test it
# should work raw_input() except time out ti = timeoutinput(poll_period=0.05) s = ti.input(prompt='wait timeout:', timeout=5.0, extend_timeout_with_input=false, require_enter_to_confirm=false) print(s)
repeated input
this implements original intention understand it. don't see value making recursive calls - think want input repeatedly? please correct me if wrong.
ti = timeoutinput() prompt = "hello me you're looking for?" timeout = 4.0 while true: # some_function() s = ti.input(prompt, timeout) if s.lower() == 'q': print "goodbye" break
Comments
Post a Comment