Python - выбрать на небуферизованном стандартном - PullRequest
0 голосов
/ 21 апреля 2020

Я действительно борюсь с буферизацией в python3. Я пытаюсь реализовать простое радио.

У меня есть класс приемника. Он отображает доступные станции для пользователя. Эти станции являются динамическими c, поэтому они появляются и исчезают.

Welcome to the radio, select station you want to listen to.
> 1) Rock Station
  2) Hip Hop Station
  3) Country Station

Таким образом, получатель должен ждать ввода как из канала (информация о появлении / исчезновении новой станции), так и из Stdin. (пользователь может использовать стрелки вверх и вниз для смены станции).

Более того, поскольку пользователь меняет станции с помощью клавиш со стрелками, я должен читать по одному символу за раз из стандартного ввода.

Это почему стандарт select.select не работает (он ждет, когда пользователь нажмет клавишу ВВОД):


class _GetchUnix:
    def __init__(self):
        import tty, sys

    def __call__(self):
        import sys, tty, termios
        fd = sys.stdin.fileno()
        old_settings = termios.tcgetattr(fd)
        try:
            tty.setraw(sys.stdin.fileno())
            ch = sys.stdin.read(1)
        finally:
            termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
        return ch


self.char_reader = _GetchUnix()
[...]

def __read_order_from_user(self,):
    k = self.char_reader()
    # Check for up/down arrow keys.
    if k == '\x1b':
        k = self.char_reader()
        if k != '[':
            return
        k = self.char_reader()
        if k == 'A':
            self.__arrow_down()
        if k == 'B':
            self.__arrow_up()

    # And check for enter key.
    if k == '\r':
        self.menu[self.option].handler()


def __update_stations(self,):
    [...]

def run(self):
    self.display()
    while True:
        rfds, _, _ = select.select([pipe, sys.stdin], [], [])

        if pipe in rfds:
                self.__update_stations()

        if sys.stdin in rfds:
            self.__read_order_from_user()

Я нашел в inte rnet, как читать один за другим символ из stdin: Python читает один символ от пользователя , и он работает, но не при использовании вместе с select.select.

1 Ответ

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

Я вставляю решение из комментария VPfB здесь:

"Необработанный режим tty включается только для чтения одного символа, а затем выключается. Когда выбор активен, он отключается, потому что процедура выбора одного символа вызывается после выбора. Вы должны включить необработанный ввод tty перед выбором l oop и восстановить настройку tty после выхода из l oop. "

...