键盘输入超时?

Posted

技术标签:

【中文标题】键盘输入超时?【英文标题】:Keyboard input with timeout? 【发布时间】:2010-11-23 01:24:54 【问题描述】:

如何提示用户输入一些内容但在 N 秒后超时?

谷歌在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

except 无法捕捉到。

【问题讨论】:

相关:Python 3 Timed Input Timeout on a Python function call的可能重复 相关:raw_input and timeout /3471461 相关:How to set time limit on input /2933399 独立于平台的 stdlib 解决方案,用于多个输入直到超时:link 【参考方案1】:

您可以在 Python >= 3.4 中使用 inputimeout 库。 麻省理工学院许可证。

$ pip install inputimeout

from inputimeout import inputimeout, TimeoutOccurred
try:
    something = inputimeout(prompt='>>', timeout=5)
except TimeoutOccurred:
    something = 'something'
print(something)

【讨论】:

【参考方案2】:

我正在使用外部工具 inputimeout 。源代码可在github 获得。我知道它是一个外部工具,但它很简单而且非常方便。 安装工具后使用此代码:

from inputimeout import inputimeout, TimeoutOccurred
try:
    something = inputimeout(prompt='>>', timeout=5)
except TimeoutOccurred:
    something = 'No input.'
print(something)

【讨论】:

【参考方案3】:

如果您不在乎它是如何工作的,只需 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)

这么简单https://pypi.org/project/inputimeout/

【讨论】:

仅供参考:来自 PyPi 的链接有错字,目前有开放的 PR (#6/#9) 来修复它。源代码在这里:github.com/johejo/inputimeout 在 Windows 上工作!【参考方案4】:

这是 linux 上的 python 3.8+ 的另一个,其中包括一个 yes_no 答案,默认返回超时

import signal
def alarm_handler(signum, frame):
    raise TimeoutError
def input_with_timeout(prompt, timeout=30):
    """ get input with timeout

    :param prompt: the prompt to print
    :param timeout: timeout in seconds, or None to disable

    :returns: the input
    :raises: TimeoutError if times out
    """
    # set signal handler
    if timeout is not None:
        signal.signal(signal.SIGALRM, alarm_handler)
        signal.alarm(timeout) # produce SIGALRM in `timeout` seconds
    try:
        return input(prompt)
    except TimeoutError as to:
        raise to
    finally:
        if timeout is not None:
            signal.alarm(0) # cancel alarm

def yes_or_no(question, default='y', timeout=None):
    """ Get y/n answer with default choice and optional timeout

    :param question: prompt
    :param default: the default choice, i.e. 'y' or 'n'
    :param timeout: the timeout in seconds, default is None

    :returns: True or False
    """
    if default is not None and (default!='y' and default!='n'):
        log.error(f'bad option for default: default')
        quit(1)
    y='Y' if default=='y' else 'y'
    n='N' if default=='n' else 'n'
    while "the answer is invalid":
        try:
            to_str='' if timeout is None else f'(Timeout default in timeouts)'
            reply = str(input_with_timeout(f'question to_str (y/n): ',timeout=timeout)).lower().strip()
        except TimeoutError:
            log.warning(f'timeout expired, returning default=default answer')
            reply=''
        if len(reply)==0:
            return True if default=='y' else False
        elif reply[0] == 'y':
            return True
        if reply[0] == 'n':
            return False

代码中的使用示例


if yes_or_no(f'model latest_model_folder exists, start from it?', timeout=TIMEOUT):
     log.info(f'initializing model from latest_model_folder')
     model = load_model(latest_model_folder)
else:
     log.info('creating new empty model')
     model = create_model()

【讨论】:

【参考方案5】:

有些答案需要在超时发生时按下Enter 键才能继续运行您的代码。其他的似乎很费解,要开机,超时后仍然需要按Enter键。

我找到了answer in another thread,它工作得很好,但我发现了一个警告。为了便于携带,我决定将我的代码放在class 中。

注意

我不得不使用@987654322@ 来注入Enter 按键,因为我的代码中有另一个input() 语句。由于某种原因,除非我按下Enter 键,否则不会出现后续的input() 语句。

import threading
import keyboard    # https://github.com/boppreh/keyboard

class Utilities:

    # Class variable
    response = None

    @classmethod
    def user_input(cls, timeout):

        def question():
            cls.response = input("Enter something: ")

        t = threading.Thread(target=question)
        # Daemon property allows the target function to terminate after timeout
        t.daemon = True    
        t.start()
        t.join(timeout)

        if cls.response:
            # Do something
        else:
            # Do something else
            # Optional.  Use if you have other input() statements in your code
            keyboard.send("enter")

用法

Utilities.user_input(3)

这是在 Windows 10 上使用 Python 3.8.3 制作的。

【讨论】:

【参考方案6】:

这是一个 Python 3.8+(虽然它可以适应 Python 3.6+)跨平台方法,只使用threading(所以没有multiprocessing或调用 shell 实用程序)。它旨在从命令行运行脚本,不太适合动态使用。

您可以将内置的input 函数包装如下。在这种情况下,我将内置名称input 重新定义为包装器,因为此实现要求对input 的所有调用都通过此路由。 (免责声明:这就是为什么它可能不是一个好主意,只是为了好玩而已。)

import atexit
import builtins
import queue
import threading


def _make_input_func():
    prompt_queue = queue.Queue(maxsize=1)
    input_queue = queue.Queue(maxsize=1)

    def get_input():
        while (prompt := prompt_queue.get()) != GeneratorExit:
            inp = builtins.input(prompt)
            input_queue.put(inp)
            prompt_queue.task_done()

    input_thread = threading.Thread(target=get_input, daemon=True)

    last_call_timed_out = False

    def input_func(prompt=None, timeout=None):
        """Mimics :function:`builtins.input`, with an optional timeout

        :param prompt: string to pass to builtins.input
        :param timeout: how long to wait for input in seconds; None means indefinitely

        :return: the received input if not timed out, otherwise None
        """
        nonlocal last_call_timed_out

        if not last_call_timed_out:
            prompt_queue.put(prompt, block=False)
        else:
            print(prompt, end='', flush=True)

        try:
            result = input_queue.get(timeout=timeout)
            last_call_timed_out = False
            return result
        except queue.Empty:
            print(flush=True) # optional: end prompt line if no input received
            last_call_timed_out = True
            return None


    input_thread.start()
    return input_func


input = _make_input_func()
del _make_input_func

(我在一次性_make_input_func 中定义了设置以在其闭包中隐藏input 的“静态”变量,以避免污染全局命名空间。)

这里的想法是创建一个单独的线程来处理对builtins.input 的所有调用,并使input 包装器管理超时。由于对builtins.input 的调用总是阻塞直到有输入,当超时结束时,特殊线程仍在等待输入,但input 包装器返回(使用None)。下次调用时,如果上次调用超时,则不需要再次调用builtins.input(因为输入线程已经在等待输入),只打印提示,然后等待该线程返回一些输入,一如既往。

定义以上内容后,尝试运行以下脚本:

import time

if __name__ == '__main__':
    timeout = 2
    start_t = time.monotonic()
    if (inp := input(f"Enter something (you have timeout seconds): ", timeout)) is not None:
        print("Received some input:", repr(inp))
    else:
        end_t = time.monotonic()
        print(f"Timed out after end_t - start_t seconds")

    inp = input("Enter something else (I'll wait this time): ")
    print("Received some input:", repr(inp))
    
    input(f"Last chance to say something (you have timeout seconds): ", timeout)

【讨论】:

【参考方案7】:

已经好几年了,但如果有人碰到这个问题,就像我最近尝试解决这类问题一样,使用func-timeout 包有一种简单快捷的方法来实现这一点。 对于大多数 IDE,它必须在使用前安装;您可以通过pip 安装它。 上面的链接是不言自明的,但我将举例说明我是如何实现它的。

from func_timeout import FunctionTimedOut, func_timeout

try:
   ans = func_timeout(5, lambda: int(input('What is the sum of 2 and 3?\n')))
   print(ans)
except FunctionTimedOut:
   print(5)

func_timeout 在其参数中返回方法的值,在本例中为 question() 函数。它还允许函数所需的其他参数(请参阅文档)。 如果设置的时间过去了(这里是 5 秒),它会引发 TimedOutException 并运行 except 块中的代码。

【讨论】:

这永远不会正常工作:任何对input 的调用都会无限期地阻塞,直到收到一些输入,并且没有办法摆脱。坦率地说,func-timeout 的实现非常糟糕:它试图通过反复“注入”异常来杀死线程,但它甚至不能确保这些异常完成工作(在这种情况下它们不会),它只是等待任意数量并声明线程已成功停止。这意味着stdin 将保持阻塞状态,任何后续的输入调用都将无法正常工作;任何输入都将首先转到 那个 input 调用。 (续) ... 此外,当程序终止时,会发生致命错误,因为 stdin 仍然被守护线程中的 input 调用阻塞:Fatal Python error: could not acquire lock for &lt;_io.BufferedReader name='&lt;stdin&gt;'&gt; at interpreter shutdown, possibly due to daemon threads【参考方案8】:
from threading import Thread
import time


def get_input():
    while True:
        print(input('> '))


t1 = Thread(target=get_input)
t1.setDaemon(True)
t1.start()
time.sleep(3)
print('program exceeds')

只需简单地设置一个新的守护线程,并设置一个睡眠时间,无论你想要什么超时。我认为这很容易赶上XD

【讨论】:

【参考方案9】:

受 iperov 的回答启发的解决方案,希望更简洁:

import multiprocessing
import sys

def input_with_timeout(prompt, timeout=None):
    """Requests the user to enter a code at the command line."""
    queue = multiprocessing.Queue()
    process = multiprocessing.Process(
        _input_with_timeout_process, args=(sys.stdin.fileno(), queue, prompt),
    )
    process.start()
    try:
        process.join(timeout)
        if process.is_alive():
            raise ValueError("Timed out waiting for input.")
        return queue.get()
    finally:
        process.terminate()


def _input_with_timeout_process(stdin_file_descriptor, queue, prompt):
    sys.stdin = os.fdopen(stdin_file_descriptor)
    queue.put(input(prompt))

【讨论】:

【参考方案10】:

对于 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

【讨论】:

对于那些想知道的人 - 这在 Ubuntu 18.04 / 20.04 和 Debian 10 (Buster) 上的 Python 3.7 和 3.8 上完美运行。简短、简单,而且效果很好!【参考方案11】:

这就是我处理这个问题的方式。我还没有彻底测试过,我不确定它没有一些重要的问题,但考虑到其他解决方案也远非完美,我决定分享:

import sys
import subprocess


def switch():
    if len(sys.argv) == 1:
        main()
    elif sys.argv[1] == "inp":
        print(input(''))
    else:
        print("Wrong arguments:", sys.argv[1:])


def main():
    passw = input_timed('You have 10 seconds to enter password:', timeout=10)
    if passw is None:
        print("Time's out! You explode!")
    elif passw == "PasswordShmashword":
        print("H-h-how did you know you h-h-hacker")
    else:
        print("I spare your life because you at least tried")


def input_timed(*args, timeout, **kwargs):
    """
    Print a message and await user input - return None if timedout
    :param args: positional arguments passed to print()
    :param timeout: number of seconds to wait before returning None
    :param kwargs: keyword arguments passed to print()
    :return: user input or None if timed out
    """
    print(*args, **kwargs)
    try:
        out: bytes = subprocess.run(["python", sys.argv[0], "inp"], capture_output=True, timeout=timeout).stdout
    except subprocess.TimeoutExpired:
        return None
    return out.decode('utf8').splitlines()[0]


switch()

【讨论】:

你制作了另一个python实例?如果需要一个额外的 python 实例,我不喜欢它。【参考方案12】:

修改后的 iperov 答案对我有用 (python3 win10 2019-12-09)

对 iperov 的更改:

将str替换为sstr,因为str是python中的函数

添加导入

添加睡眠以降低 while 循环的 CPU 使用率 (?)

add if name=='ma​​in': #windows 上的多处理需要

导入系统、操作系统、多进程、时间

def input_process(stdin_fd, sq, sstr):
    sys.stdin = os.fdopen(stdin_fd)
    try:
        inp = input(sstr)
        sq.put(True)
    except:
        sq.put(False)

def input_in_time(sstr, max_time_sec):
    sq = multiprocessing.Queue()
    p = multiprocessing.Process(target=input_process, args=( sys.stdin.fileno(), sq, sstr))
    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

        tleft=int( (t+max_time_sec)-time.time())
        if tleft<max_time_sec-1 and tleft>0:
            print('\n  ...time left '+str(tleft)+'s\ncommand:')

        time.sleep(2)

    p.terminate()
    sys.stdin = os.fdopen( sys.stdin.fileno() )
    return inp

if __name__=='__main__':
    input_in_time("command:", 17)

【讨论】:

【参考方案13】:

我的跨平台解决方案

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

【讨论】:

看起来不错,需要试试这个,在while循环中添加sleep不使用太多cpu有意义吗? 尚未测试此解决方案,但我认为不需要睡眠,因为get() 会阻塞直到结果可用。请参阅文档:docs.python.org/3/library/queue.html#queue.Queue.get【参考方案14】:

这是一个使用线程的可移植且简单的 Python 3 解决方案。 这是跨平台时唯一对我有用的。

我试过的其他东西都有问题:

使用 signal.SIGALRM:在 Windows 上不起作用 使用选择调用:不适用于 Windows 使用强制终止进程(而不是线程):标准输入不能用于新进程(标准输入自动关闭) 将标准输入重定向到 StringIO 并直接写入标准输入:如果 input() 已被调用,仍将写入先前的标准输入(请参阅https://***.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_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

【讨论】:

这种方法有效,但线程超时运行。【参考方案15】:

以下代码对我有用。

我使用了两个线程,一个用于获取 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()

【讨论】:

【参考方案16】:

保罗的回答不太奏效。下面的修改代码对我有用

Windows 7 x64

vanilla CMD shell(例如,not 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) 

【讨论】:

格式化无法正常工作。我很难过,在 Meta 上问过:meta.stackexchange.com/q/290162/208995 当我尝试这个时,我无法输入任何内容(它会等待 5 秒而不让我输入任何内容)。【参考方案17】:

类似于 Locane 的 windows:

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

【讨论】:

如果重要的话,超时是在 Windows Vista 中或之后引入的。【参考方案18】:

不是 Python 解决方案,而是...

我在 CentOS (Linux) 下运行的脚本遇到了这个问题,而对我的情况有用的只是在子进程中运行 Bash“read -t”命令。残酷的令人作呕的黑客,我知道,但我对它的效果感到内疚,所以我想在这里与大家分享。

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

我所需要的只是等待 30 秒,除非按下 ENTER 键。这效果很好。

【讨论】:

【参考方案19】:

我在这上面花了大约 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()

【讨论】:

很好的解决方案。在 Python3 中工作得很好。投票不够。【参考方案20】:

一个迟到的答案:)

我会这样做:

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

我知道这不一样,但许多现实生活中的问题都可以通过这种方式解决。 (如果用户暂时不在那里,当我希望某些东西继续运行时,我通常需要用户输入超时。)

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

【讨论】:

否,KeyboardInterrupt 异常发生在用户发送中断信号时,通常是在终端上按Ctrl+C。【参考方案21】:

这是适用于 Windows 的一个

我无法让这些示例中的任何一个在 Windows 上运行,因此我合并了一些不同的 *** 答案以获得以下结果:


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 

【讨论】:

我刚刚意识到我不需要使用线程。在***.com/questions/3471461/raw-input-and-timeout/… 看到相同的代码但没有线程 这似乎不适用于 Windows。除了将 Print 更改为 py3 语法并添加 stdout.flush() 之外,我正在逐字运行您的代码。 Windows7、python3.6 在 Python 3 中,将 sys.stdout.write 替换为 print(prompt, end='', flush=True) 以打印提示。【参考方案22】:

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

【讨论】:

我刚刚测试过,这不适用于 Windows。 Select 是可用的,但在 Windows 上,select 的输入只能是一个套接字 - sys.stdin 和文件描述符是 unix。下次我一定要先测试。 该死。那么,有什么自尊的程序员使用 Windows 呢? ;) 对于简单的用户输入,我想它可以通过围绕“kbhit”的循环来完成,该循环检测键盘按下,并用“time.sleep”“getch”在超时后中断。但这会很丑。 如果您打算在此调用之后再次从标准输入读取,最好在读取超时的情况下执行termios.tcflush(sys.stdin, termios.TCIFLUSH)。否则,如果用户输入了字符但没有按 Enter,则终端仿真器可能允许用户按退格键并擦除后续程序输出(最多为用户输入的字符数)。【参考方案23】:

您链接到的示例是错误的,异常实际上是在调用警报处理程序而不是在读取块时发生的。最好试试这个:

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

【讨论】:

我今天一直在努力让键盘输入超时。我只是想要一种方法来停止从硬盘驱动器复制图像,这样我只需按一个键就可以停止它,所以我想要一个小的超时(33ms)。我只想指出,您在 *** 上找到的一些解决方案不适用于 IDLE! (我不知道为什么)。您必须在终端上执行它们。而且,我在互联网上找到的最有用的代码是这个:home.wlu.edu/~levys/software/kbhit.py。祝你好运! 我正在尝试这个解决方案,但这在 python3 中不起作用。您必须在中断函数中引发错误才能在定义的输入函数中捕获该异常 - 这将使其在 python3 中工作。 :) 这对我不起作用。它只是在 5 秒后打印 "interrupted",但实际上并没有停止 input。它仍然等待 Enter 被按下,甚至在“中断”消息出现后打印我输入的任何文本。使用 Python 2 和 3 在 Linux 上测试。 引用库文档的链接非常有用,以便在它对某人不起作用的情况下进行调试。 您需要为此定义一个处理程序。例如,“def handler(signum, frame): raise IOError”然后是“signal.signal(signal.SIGALRM, handler)”

以上是关于键盘输入超时?的主要内容,如果未能解决你的问题,请参考以下文章

键盘输入超时?

键盘输入在Python中超时

Shell基础--read接受键盘输入

c++实现键盘记录仪(键盘钩子)

WPF 窗体中获取键盘和鼠标无操作时的超时提示

delphi键盘钩子没效果