如何设置 raw_input 的时间限制 [英] How to set time limit on raw_input
问题描述
在 python 中,有没有办法在等待用户输入时计算时间,以便在 30 秒后自动跳过 raw_input()
函数?
in python, is there a way to, while waiting for a user input, count time so that after, say 30 seconds, the raw_input()
function is automatically skipped?
推荐答案
signal.alarm 函数仅适用于 Unix.如果您需要跨平台或特定于 Windows 的解决方案,您可以基于 threading.Timer 代替,使用 thread.interrupt_main 将 KeyboardInterrupt
从定时器线程发送到主线程.即:
The signal.alarm function, on which @jer's recommended solution is based, is unfortunately Unix-only. If you need a cross-platform or Windows-specific solution, you can base it on threading.Timer instead, using thread.interrupt_main to send a KeyboardInterrupt
to the main thread from the timer thread. I.e.:
import thread
import threading
def raw_input_with_timeout(prompt, timeout=30.0):
print(prompt, end=' ')
timer = threading.Timer(timeout, thread.interrupt_main)
astring = None
try:
timer.start()
astring = input(prompt)
except KeyboardInterrupt:
pass
timer.cancel()
return astring
无论是 30 秒超时还是用户明确决定点击 control-C 放弃输入任何内容,这都将返回 None,但以相同的方式处理这两种情况似乎可以(如果您需要区分,您可以为计时器使用自己的函数,在中断主线程之前,在某处记录发生超时的事实已经,并在您的处理程序中用于 KeyboardInterrupt
访问那个某处"来区分发生了两种情况中的哪一种).
this will return None whether the 30 seconds time out or the user explicitly decides to hit control-C to give up on inputting anything, but it seems OK to treat the two cases in the same way (if you need to distinguish, you could use for the timer a function of your own that, before interrupting the main thread, records somewhere the fact that a timeout has happened, and in your handler for KeyboardInterrupt
access that "somewhere" to discriminate which of the two cases occurred).
编辑:我可以发誓这是有效的,但我一定是错的——上面的代码省略了明显需要的timer.start()
, 和 即使有了它,我也不能让它再工作了.select.select
显然是另一件要尝试的事情,但它不适用于 Windows 中的普通文件"(包括 stdin)——在 Unix 中它适用于所有文件,在 Windows 中,仅适用于在插座上.
Edit: I could have sworn this was working but I must have been wrong -- the code above omits the obviously-needed timer.start()
, and even with it I can't make it work any more. select.select
would be the obvious other thing to try but it won't work on a "normal file" (including stdin) in Windows -- in Unix it works on all files, in Windows, only on sockets.
所以我不知道如何进行跨平台的原始输入超时".可以使用紧密循环轮询 msvcrt 构建特定于 Windows 的轮询.kbhit,执行 msvcrt.getche
(并检查它是否是一个返回以指示输出完成,在这种情况下它会跳出循环,否则会累积并继续等待)并检查如果需要,超时时间.我无法测试,因为我没有 Windows 机器(它们都是 Mac 和 Linux 机器),但在这里我建议使用 未经测试的代码:
So I don't know how to do a cross-platform "raw input with timeout". A windows-specific one can be constructed with a tight loop polling msvcrt.kbhit, performing a msvcrt.getche
(and checking if it's a return to indicate the output's done, in which case it breaks out of the loop, otherwise accumulates and keeps waiting) and checking the time to time out if needed. I cannot test because I have no Windows machine (they're all Macs and Linux ones), but here the untested code I would suggest:
import msvcrt
import time
def raw_input_with_timeout(prompt, timeout=30.0):
print(prompt, end=' ')
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 说他不想在超时时return None
,但是有什么替代方法?引发异常?返回不同的默认值?无论他想要什么替代方案,他都可以清楚地用它代替我的 return None
;-).
The OP in a comment says he does not want to return None
upon timeout, but what's the alternative? Raising an exception? Returning a different default value? Whatever alternative he wants he can clearly put it in place of my return None
;-).
如果您不想仅仅因为用户输入缓慢而超时(而不是根本不输入!-),您可以在每次成功输入字符后重新计算finishat.
If you don't want to time out just because the user is typing slowly (as opposed to, not typing at all!-), you could recompute finishat after every successful character input.
这篇关于如何设置 raw_input 的时间限制的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!