Как читать одиночные нажатия клавиш, не блокируя все приложение? - PullRequest
0 голосов
/ 08 апреля 2020

Поскольку я не нашел лучшего способа читать нажатия клавиш в командной строке, я в настоящее время использую getch().

К сожалению, использование getch() как это останавливает вывод на stdout:

while True:
    handle_keystroke(getch())

Нажатие кнопок запускает handle_keystroke() и stdout печатается в терминале - строка за строкой для каждого нажатия клавиши.

Предоставленные рекомендации здесь не помогло.

Что я делаю не так?

Кстати: мне не нужно для использования getch(). Есть ли лучший способ (например, с использованием select())?

Обновление: (изменил название)

Все это становится проблемой только при использовании более чем одна нить. Похоже, что getch (которая не является Python функцией) не освобождает GIL, поэтому все другие потоки приостанавливаются, поэтому затрагивается не только stdout.

1 Ответ

0 голосов
/ 08 апреля 2020

Хорошо, нашел способ использовать select вместо getch(). Хитрость заключается в том, чтобы установить режим sys.stdout на 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)
...