键盘input与Python超时

你会如何提示用户input一些信息,但在N秒后超时?

Google正在http://mail.python.org/pipermail/python-list/2006-January/533215.html指向一个关于它的邮件主题,但似乎不起作用。 在发生超时的语句中,不pipe是sys.input.readline还是timer.sleep(),我都会得到:

<type'exception.TypeError'>:[raw_]input最多1个参数,得到2

不知何故,除了没有抓住。

你链接的例子是错误的,这个exception实际发生在调用报警处理程序而不是读取块时。 最好试试这个:

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 

使用select调用的时间更短,而且应该更便于携带

 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!" 

不是Python的解决scheme,但…

我在CentOS(Linux)下运行一个脚本,遇到了这个问题,我的情况是在subprocess中运行Bash“read -t”命令。 我知道,残酷的恶意攻击,但是我觉得它的工作效果很好,我想和大家分享一下。

 import subprocess subprocess.call('read -t 30', shell=True) 

我只需要等待30秒,除非按下ENTER键。 这很好。

这是一个在Windows上工作的

我还没有能够得到任何这些例子在Windows上工作,所以我已经合并了一些不同的StackOverflow的答案,以获得以下内容:

 import threading, msvcrt import sys def readInput(caption, default, timeout = 5): class KeyboardThread(threading.Thread): def run(self): self.timedout = False self.input = '' while True: if msvcrt.kbhit(): chr = msvcrt.getche() if ord(chr) == 13: break elif ord(chr) >= 32: self.input += chr if len(self.input) == 0 and self.timedout: break sys.stdout.write('%s(%s):'%(caption, default)); result = default it = KeyboardThread() it.start() it.join(timeout) it.timedout = True if len(it.input) > 0: # wait for rest of input it.join() result = it.input print '' # needed to move to next line return result # and some examples of usage ans = readInput('Please type a name', 'john') print 'The name is %s' % ans ans = readInput('Please enter a number', 10 ) print 'The number is %s' % ans 

以下代码为我工作。

我使用了两个线程来获取raw_Input,另一个线程等待特定的时间。 如果任何线程退出,则线程终止并返回。

 def _input(msg, q): ra = raw_input(msg) if ra: q.put(ra) else: q.put("None") return def _slp(tm, q): time.sleep(tm) q.put("Timeout") return def wait_for_input(msg="Press Enter to continue", time=10): q = Queue.Queue() th = threading.Thread(target=_input, args=(msg, q,)) tt = threading.Thread(target=_slp, args=(time, q,)) th.start() tt.start() ret = None while True: ret = q.get() if ret: th._Thread__stop() tt._Thread__stop() return ret return ret print time.ctime() t= wait_for_input() print "\nResponse :",t print time.ctime() 

我花了二十分钟左右的时间,所以我认为这是值得一试的。 不过,它直接build立在user137673的答案上。 我发现这样做最有用:

 #! /usr/bin/env python import signal timeout = None def main(): inp = stdinWait("You have 5 seconds to type text and press <Enter>... ", "[no text]", 5, "Aw man! You ran out of time!!") if not timeout: print "You entered", inp else: print "You didn't enter anything because I'm on a tight schedule!" def stdinWait(text, default, time, timeoutDisplay = None, **kwargs): signal.signal(signal.SIGALRM, interrupt) signal.alarm(time) # sets timeout global timeout try: inp = raw_input(text) signal.alarm(0) timeout = False except (KeyboardInterrupt): printInterrupt = kwargs.get("printInterrupt", True) if printInterrupt: print "Keyboard interrupt" timeout = True # Do this so you don't mistakenly get input when there is none inp = default except: timeout = True if not timeoutDisplay is None: print timeoutDisplay signal.alarm(0) inp = default return inp def interrupt(signum, frame): raise Exception("") if __name__ == "__main__": main() 

类似于Locane的窗户:

 import subprocess subprocess.call('timeout /T 30') 

保罗的回答并不完美。 修改后的代码适用于我

  • Windows 7 x64

  • 香草CMD shell(例如, 不是 git-bash或其他非M $ shell)

    – 没有什么msvcrt在git-bash中出现。

  • python 3.6

(我发布了一个新的答案,因为直接编辑Paul的答案会改变它从python 2.x – > 3.x,这似乎太多编辑(py2仍在使用中)

 import sys, time, msvcrt def readInput( caption, default, timeout = 5): start_time = time.time() sys.stdout.write('%s(%s):'%(caption, default)) sys.stdout.flush() input = '' while True: if msvcrt.kbhit(): byte_arr = msvcrt.getche() if ord(byte_arr) == 13: # enter_key break elif ord(byte_arr) >= 32: #space_char input += "".join(map(chr,byte_arr)) if len(input) == 0 and (time.time() - start_time) > timeout: print("timing out, using default value.") break print('') # needed to move to next line if len(input) > 0: return input else: return default # and some examples of usage ans = readInput('Please type a name', 'john') print( 'The name is %s' % ans) ans = readInput('Please enter a number', 10 ) print( 'The number is %s' % ans) 

迟到的回答:)

我会做这样的事情:

 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.') 

我知道这是不一样的,但许多现实生活中的问题可以通过这种方式来解决。 (如果用户不在此刻,我想要继续运行,我通常需要用户input超时。)

希望这至less有部分帮助。 (如果有人读它:))