键盘输入在Python中超时
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了键盘输入在Python中超时相关的知识,希望对你有一定的参考价值。
你会如何提示用户输入一些信息但是在N秒后超时?
谷歌在http://mail.python.org/pipermail/python-list/2006-January/533215.html指向一个关于它的邮件线程,但似乎没有用。超时发生的语句,无论是sys.input.readline还是timer.sleep(),我总是得到:
<type'exception.TypeError'>:[raw_]输入最多需要1个参数,得2
以某种方式,除了没有抓住。
您链接到的示例是错误的,并且在调用警报处理程序而不是读取块时实际发生异常。最好试试这个:
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
我的跨平台解决方案
def input_process(stdin_fd, sq, str):
sys.stdin = os.fdopen(stdin_fd)
try:
inp = input (str)
sq.put (True)
except:
sq.put (False)
def input_in_time (str, max_time_sec):
sq = multiprocessing.Queue()
p = multiprocessing.Process(target=input_process, args=( sys.stdin.fileno(), sq, str))
p.start()
t = time.time()
inp = False
while True:
if not sq.empty():
inp = sq.get()
break
if time.time() - t > max_time_sec:
break
p.terminate()
sys.stdin = os.fdopen( sys.stdin.fileno() )
return inp
迟到的答案:)
我会做这样的事情:
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.')
我知道这不一样,但许多现实生活中的问题都可以通过这种方式解决。 (如果用户现在没有在那里继续运行,我通常需要超时用户输入。)
希望这至少部分有帮助。 (如果有人再读它:))
使用选择呼叫更短,并且应该更加便携
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解决方案,但......
我在CentOS(Linux)下运行的脚本遇到了这个问题,对我的情况有用的只是在子进程中运行Bash“read -t”命令。我知道,野蛮恶心的黑客,但我对它的运作情况感到内疚,我想与大家分享。
import subprocess
subprocess.call('read -t 30', shell=True)
除非按下ENTER键,否则我需要的是等待30秒的东西。这很有效。
这是一个适用于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
保罗的答案并不奏效。修改后的代码对我有用
- Windows 7 x64
- vanilla 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)
我花了大约20分钟左右的时间,所以我觉得值得一试把它放在这里。不过,它直接建立在用户137673的答案之上。我发现做这样的事情最有用:
#! /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()
以下代码为我工作。
我使用两个线程来获取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 "
Response :",t
print time.ctime()
类似于Locane的Windows:
import subprocess
subprocess.call('timeout /T 30')
这是一个使用线程的可移植且简单的Python 3解决方案。这是跨平台时唯一适合我的方法。
我尝试过的其他事情都有问题:
- 使用signal.SIGALRM:不在Windows上运行
- 使用select call:不在Windows上运行
- 使用强制终止进程(而不是线程):stdin不能在新进程中使用(stdin自动关闭)
- 将stdin重定向到StringIO并直接写入stdin:如果已经调用了input(),它仍将写入先前的stdin(参见https://stackoverflow.com/a/15055639/9624704)
from threading import Thread
class myClass:
_input = None
def __init__(self):
get_input_thread = Thread(target=self.get_input)
get_input_thread.daemon = True # Otherwise the thread won't be terminated when the main program terminates.
get_input_thread.start()
get_input_thr以上是关于键盘输入在Python中超时的主要内容,如果未能解决你的问题,请参考以下文章