【问题标题】:Unbuffered non-blocking keyboard input on command line命令行上的无缓冲非阻塞键盘输入
【发布时间】:2016-07-04 04:07:21
【问题描述】:

我想以非阻塞的方式立即(不等待换行)捕获命令行上的“所有”键盘输入 方式。

This question 演示了如何使用select() 以非阻塞方式读取stdin。它是这样工作的:

while True:
    if select.select([sys.stdin], [], [], 0)[0] == [sys.stdin]:
        print(sys.stdin.read(1))

    ... do other stuff ...

不幸的是,您只有在按下 RETURN 后才能得到结果。

我的第一个猜测是stdin 只是行缓冲,所以在阅读了this question 之后我把我的代码变成了

ubuf_stdin = os.fdopen(sys.stdin.fileno(), 'rb', buffering=0)
while True:
    if select.select([ubuf_stdin], [], [], 0)[0] == [ubuf_stdin]:
        print(ubuf_stdin.read(1))
    ... do other stuff ...

这段代码工作得更好——缓冲区被完全读取而没有中断——但它仍在等待RETURN被按下。

我也试过detachstdin

ubuf_stdin = os.fdopen(sys.stdin.detach().fileno(), 'rb', buffering=0)

我如何在按键后立即对键盘输入做出反应?

【问题讨论】:

  • question 的答案表明这是不可能的。

标签: python stdin nonblocking


【解决方案1】:

使用getch 模块一次获得一个按键,如this question 中所述。

我认为您无法以一次非阻塞但字符一次的方式读取标准输入,它真的不是为了那个目的。

【讨论】:

  • 嗯 - 这不可能是全部事实 - 至少 ncurses(在 POSIX 和 Windows 上都可用)可以从 stdin 字符明智地读取..
  • 我很确定 ncurses 及其变体使用的是 /dev/tty 或等效的,而不是实际的标准输入文件描述符。我也可以完全直言不讳。
  • 好吧,也许你是对的 - 我必须改变我的头衔。我真正想要的是在命令行程序中捕获键盘输入。 stdin 只是我想到的第一件事:)
  • 那么getch 可能是你最好的选择。
  • 但是getch 阻塞,不是吗?优点是使用getch,您看不到屏幕上的字符,但您必须启动线程或以某种方式select() 终端设备..
【解决方案2】:

好吧,这个可以,但它还有一些缺点:

  • 使用curses 模块,这对我来说似乎有点重
  • 必须轮询输入 - 还没有办法select()
  • 键盘输入仍会打印到终端

.. 但它有效:)。

import curses
def read_stdin(self):
    def cb(screen):
        result = []
        screen.nodelay(1)
        while True:
            try:
                result.append(screen.getkey())
            except curses.error:
                return result

    # contains a list of keys pressed since last call
    return curses.wrapper(cb)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-10-01
    • 2020-03-29
    • 1970-01-01
    • 2011-01-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多