Nano Hash - криптовалюты, майнинг, программирование

Python не блокирует обнаружение нажатия клавиши без сообщения my-tty

У меня есть цикл, который выполняет некоторую работу и выводит много информации на стандартный вывод. Снова и снова (это цикл...) Я хотел бы определить, когда/если пользователь нажимает клавишу (это может быть стрелка, ввод или буква), и выполнять некоторую работу, когда это происходит .

Это должна была быть очень простая подзадача, но последние четыре часа я пробовал разные подходы и почти ничего не добился.

Это нужно только для работы в Linux.

Лучшее, что я мог получить, это что-то вроде этого ниже. Но это работает частично, ловя ключи только если в течение 0.05 сек.

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


def getch(timeout=0.2):
    inkey = _Getch()
    k = ''
    start_sec = time()
    while(time() - start_sec < timeout):
        if k == '':
            k = timeout_call(inkey, timeout_duration=timeout - (time() - start_sec))
    if k == u'\x1b':
        k += inkey(2)
        if k == u'\x1b[A':
            return "up"
        if k == u'\x1b[B':
            return "down"
        if k == u'\x1b[C':
            return "right"
        if k == u'\x1b[D':
            return "left"
    elif k == "q":
        return 'q'
    elif k == "\n":
        return 'enter'
    else:
        return None


while True:
    do_some_work_that_lasts_about_0_2_seconds()
    key = getch(0.05)
    if key:
        do_something_with_the(key)
05.07.2014

Ответы:


1

Об этом уже спрашивали. Кто-то опубликовал хорошее, короткое, рефакторинговое решение.

Размещено здесь

import sys
import select
import tty
import termios

class NonBlockingConsole(object):

    def __enter__(self):
        self.old_settings = termios.tcgetattr(sys.stdin)
        tty.setcbreak(sys.stdin.fileno())
        return self

    def __exit__(self, type, value, traceback):
        termios.tcsetattr(sys.stdin, termios.TCSADRAIN, self.old_settings)


    def get_data(self):
        if select.select([sys.stdin], [], [], 0) == ([sys.stdin], [], []):
            return sys.stdin.read(1)
        return False


if __name__ == '__main__':
    # Use like this
    with NonBlockingConsole() as nbc:
        i = 0
        while 1:
            print i
            i += 1

            if nbc.get_data() == '\x1b':  # x1b is ESC
                break
05.07.2014
  • Одна проблема: как я могу читать клавиши со стрелками и обычные клавиши с таким подходом? Клавиши со стрелками, похоже, используют три символа, но если я сделаю return sys.stdin.read(3), консоль больше не будет неблокирующей. 09.07.2014
  • Я собираюсь принять ваш ответ, потому что он привел меня в правильном направлении. Спасибо. Но это не совсем решение для моего случая, потому что оно не поддерживает escape-последовательности. select.select кажется недостаточным для этого. 09.07.2014

  • 2

    Вот решение, которое я придумал. Не идеально, потому что он полагается на тайм-ауты и иногда может поймать только половину escape-последовательностей, если клавиша нажата милли (микро? нано?) секунд до истечения времени ожидания. Но это наименее плохое решение, которое я мог придумать. Разочаровывает...

    def timeout_call(func, args=(), kwargs=None, timeout_duration=1.0, default=None):
        if not kwargs:
            kwargs = {}
        import signal
    
        class TimeoutError(Exception):
            pass
    
        def handler(signum, frame):
            raise TimeoutError()
    
        # set the timeout handler
        signal.signal(signal.SIGALRM, handler)
        signal.setitimer(signal.ITIMER_REAL, timeout_duration)
        try:
            result = func(*args, **kwargs)
        except TimeoutError as exc:
            result = default
        finally:
            signal.alarm(0)
    
        return result
    
    
    class NonBlockingConsole(object):
    
        def __enter__(self):
            self.old_settings = termios.tcgetattr(sys.stdin)
            tty.setcbreak(sys.stdin.fileno())
            return self
    
        def __exit__(self, type, value, traceback):
            termios.tcsetattr(sys.stdin, termios.TCSADRAIN, self.old_settings)
    
        def get_data(self):
            k = ''
            while True:
                c = timeout_call(sys.stdin.read, args=[1], timeout_duration=0.05)
                if c is None:
                    break
                k += c
    
            return k if k else False
    

    Использование:

    with NonBlockingConsole() as nbc:
        while True:
            sleep(0.05)  # or longer, but not shorter, for my setup anyways...
            data = nbc.get_data()
            if data:
                print data.encode('string-escape')
    
    08.07.2014
    Новые материалы

    Кластеризация: более глубокий взгляд
    Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

    Как написать эффективное резюме
    Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

    Как я автоматизирую тестирование с помощью Jest
    Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

    Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
    В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..