谷歌指向一个邮件线程(http://mail.python.org/pipermail/python-list/2006-January/533215.html),但它似乎不起作用。无论是
sys.input.readline
还是timer.sleep()
发生超时的语句,我总是得到:<type 'exceptions.TypeError'>: [raw_]input expected at most 1 arguments, got 2
某种情况下,异常未被捕获。
sys.input.readline
还是timer.sleep()
发生超时的语句,我总是得到:<type 'exceptions.TypeError'>: [raw_]input expected at most 1 arguments, got 2
某种情况下,异常未被捕获。
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!"
termios.tcflush(sys.stdin, termios.TCIFLUSH)
。否则,如果用户输入了字符但没有按Enter键,终端仿真器可能会允许用户按退格键并擦除程序的后续输出(直到用户输入的字符数)。 - iafisher你提供的示例是错误的,实际上异常发生在调用闹钟处理程序时而不是阻塞读取时。建议使用以下代码:
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
input
的执行。它仍然等待用户按下Enter键,即使在“Interrupted”消息出现后输入任何文本,它也会将其打印出来。在Linux上使用Python 2和3进行了测试。 - tobias_k如果您不关心它是如何工作的,只需执行
pip install inputimeout
即可。
from inputimeout import inputimeout, TimeoutOccurred
if __name__ == "__main__":
try:
c = inputimeout(prompt='hello\n', timeout=3)
except TimeoutOccurred:
c = 'timeout'
print(c)
虽然不是Python解决方案,但...
我在运行CentOS (Linux)下的脚本时遇到了这个问题,对于我的情况,只需在子进程中运行Bash "read -t"命令即可解决。这是一种残酷、恶心的hack方式,但它的工作效果让我感到内疚,我希望与大家分享。
import subprocess
subprocess.call('read -t 30', shell=True)
我需要的是等待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
print(prompt, end='', flush=True)
替换sys.stdout.write
来打印提示信息。 - Anakhand保罗的答案并没有完全起作用。 下面是修改后的代码,这在我的以下设置中可以运行:
windows 7 x64
普通CMD shell(例如,不是 git-bash或其他非M $ shell)
-- 在git-bash中似乎没有任何msvcrt
可用。
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分钟的时间,所以我认为把这个分享出来是值得一试的。这是直接基于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()
以下代码对我有用。
我使用了两个线程,一个用于获取原始输入(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()
对于Linux系统,我更喜欢由@Pontus提供的select
版本。在此,只需一个Python3函数即可像shell中的read
一样工作:
import sys, select
def timeout_input(prompt, timeout=3, default=""):
print(prompt, end=': ', flush=True)
inputs, outputs, errors = select.select([sys.stdin], [], [], timeout)
print()
return (0, sys.stdin.readline().strip()) if inputs else (-1, default)
运行
In [29]: timeout_input("Continue? (Y/n)", 3, "y")
Continue? (Y/n):
Out[29]: (-1, 'y')
In [30]: timeout_input("Continue? (Y/n)", 3, "y")
Continue? (Y/n): n
Out[30]: (0, 'n')
还有一个yes_or_no
函数
In [33]: yes_or_no_3 = lambda prompt: 'n' not in timeout_input(prompt + "? (Y/n)", 3, default="y")[1].lower()
In [34]: yes_or_no_3("Continue")
Continue? (Y/n):
Out[34]: True
In [35]: yes_or_no_3("Continue")
Continue? (Y/n): no
Out[35]: False
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_thread.join(timeout=20)
if myClass._input is None:
print("No input was given within 20 seconds")
else:
print("Input given was: {}".format(myClass._input))
@classmethod
def get_input(cls):
cls._input = input("")
return