如何使用带有Python的计时器一次读取键盘输入一个字符

Mik*_*oll 0 python linux input

我试图弄清楚如何创建一个可以采用以下参数的小脚本:

  1. 提示 - 字符串
  2. 等待整数的时间
  3. 停止前的字符数

最后一个是在程序停止接受字符并开始处理输入之前我可以输入的字符数.我见过有些人使用Python的select.select 方法,但这并没有考虑到第3项.我倾向于诅咒,虽然我不知道它是否支持超时让我想到线程.任何见解都会很棒!这将在Linux上使用Python 2.6运行.

Mic*_*rny 6

好的,我已经实现了它:D.

#!/usr/bin/env python

import sys
from select import select

def main(argv):
    timeout = 3
    prompt = '> '
    max_chars = 3

    # set raw input mode if relevant
    # it is necessary to make stdin not wait for enter
    try:
        import tty, termios

        prev_flags = termios.tcgetattr(sys.stdin.fileno())
        tty.setraw(sys.stdin.fileno())
    except ImportError:
        prev_flags = None

    buf = ''
    sys.stderr.write(prompt)

    while True: # main loop
        rl, wl, xl = select([sys.stdin], [], [], timeout)
        if rl: # some input
            c = sys.stdin.read(1)
            # you will probably want to add some special key support
            # for example stop on enter:
            if c == '\n':
                break

            buf += c
            # auto-output is disabled as well, so you need to print it
            sys.stderr.write(c)

            # stop if N characters
            if len(buf) >= max_chars:
                break
        else:
            # timeout
            break

    # restore non-raw input
    if prev_flags is not None:
        termios.tcsetattr(sys.stdin.fileno(), termios.TCSADRAIN, prev_flags)
    # and print newline
    sys.stderr.write('\n')

    # now buf contains your input
    # ...

if __name__ == "__main__":
    main(sys.argv[1:])
Run Code Online (Sandbox Code Playgroud)

它相当不完整; 我只是给它一些值来测试它.几句解释:

  1. 您需要将tty切换为"原始"模式 - 否则,如果没有输入密钥确认,您将无法获得输入,
  2. 在原始模式下,默认情况下不再输出键入的字符 - 如果您希望用户查看他正在键入的内容,您需要自己输出它们
  3. 你可能想要处理像enter和backspace这样的特殊键 - 我在这里添加了输入处理.也许你可以重复使用它的部分curses,
  4. 我假设超时是"最后一个键后3秒".如果你想要整个过程的超时,我认为最简单的方法是获取当前时间,通过超时(即get end_time)增加它,然后end_time - current_time在超时时间内传递秒数select(),
  5. 我已经使unix特定的导入可选.不过,我不知道它是否能在Windows上正常工作.