How to read single keystrokes without blocking the whole application?

给你一囗甜甜゛ 提交于 2021-01-29 05:47:01

问题


Because I didn't find a better way to read keystrokes on command line I'm currently using getch().

Unfortunately using getch() like this stops output on stdout:

while True:
    handle_keystroke(getch())

Pressing buttons triggers handle_keystroke() and stdout is being printed in the terminal - line by line for each keystroke.

Recommendations provided here didn't help.

What do I do wrong?

Btw: I do not need to use getch(). Is there a better way (e.g. using select())?

Update: (changed the title)

All this becomes a problem only when you're using more than one thread. So it looks like getch (which is a non Python function) doesn't release the GIL, so all other threads are suspended, so not only stdout is affected.


回答1:


Ok, found a way to use select instead of getch(). The trick is to set the mode of sys.stdout to cbreak:

import select
import tty
import termios
from contextlib import contextmanager

@contextmanager
def cbreak(stream):
    """Set fd mode to cbreak"""
    old_settings = termios.tcgetattr(stream)
    tty.setcbreak(stream.fileno())
    yield
    termios.tcsetattr(stream, termios.TCSADRAIN, old_settings)

with cbreak(sys.stdin):
    while True:
        select.select([sys.stdin], [], []) == ([sys.stdin], [], [])
        key = sys.stdin.read(1)
        handle_keystroke(key)


来源:https://stackoverflow.com/questions/61098253/how-to-read-single-keystrokes-without-blocking-the-whole-application

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!