在@ jer推荐的解决方案基础上的
signal.alarm功能不幸的是Unix。如果您需要跨平台或Windows特定解决方案,则可以将其改为
threading.Timer,使用
thread.interrupt_main将KeyboardInterrupt从定时器线程发送到主线程。即:
import thread
import threading
def raw_input_with_timeout(prompt, timeout=30.0):
print prompt,
timer = threading.Timer(timeout, thread.interrupt_main)
astring = None
try:
timer.start()
astring = raw_input(prompt)
except KeyboardInterrupt:
pass
timer.cancel()
return astring
这将返回None,无论30秒超时还是用户明确决定按Ctrl-C放弃输入任何内容,但是以相同的方式处理这两种情况似乎可以(如果需要区分,可以使用对于定时器,您自己的功能,在中断主线程之前,记录某个超时发生的事实,并且在您的KeyboardInterrupt的处理程序中访问“某处”以区分两种情况中的哪一种。
编辑:我可以宣誓这是工作,但我一定是错的 – 上面的代码省略了明显需要的timer.start(),甚至与它,我不能使它工作了。 select.select将是显而易见的另一件事情,但它不会在Windows中的“正常文件”(包括stdin)上运行 – 在Unix中,它适用于Windows中的所有文件,仅适用于套接字。
所以我不知道如何做一个跨平台的“原始输入超时”。可以使用紧密循环轮询msvcrt.kbhit构建特定于Windows的窗口,执行msvcrt.getche(并检查是否返回以指示输出完成,在这种情况下,它会突破循环,否则累积并保持等待)如果需要,检查时间到时间。我无法测试,因为我没有Windows机器(他们都是Mac和Linux的),但在这里我将提出未经测试的代码:
import msvcrt
import time
def raw_input_with_timeout(prompt, timeout=30.0):
print prompt,
finishat = time.time() + timeout
result = []
while True:
if msvcrt.kbhit():
result.append(msvcrt.getche())
if result[-1] == '\r': # or \n, whatever Win returns;-)
return ''.join(result)
time.sleep(0.1) # just to yield to other processes/threads
else:
if time.time() > finishat:
return None
OP中的OP表示他不想在超时时返回None,但是有什么可选择的呢?提出异常?返回不同的默认值?无论他想要什么替代方案,他都可以清楚地把它代替我的回报没有;-)。
如果您不想超时,因为用户正在慢慢打字(而不是全部输入!),您可以在每次成功的字符输入后重新计算完成。