Реагировать на ключевые события, уже читая со стандартного ввода в Python

Настраивать

Я играл со сценарием, чтобы передать tail -f и выделить определенные ключевые слова. Не большой проект, но то, что я считаю полезным.

Прямо сейчас основной цикл в основном:

...
line = True
while line:
    line = sys.stdin.readline()
    sys.stdout.write(highlight(line))
...

Я хотел бы прослушать определенные нажатия клавиш во время этого цикла, чтобы напечатать строку маркера в журнале. Метод, который я обнаружил, который выглядит так, как будто он будет работать для получения нажатия клавиши, описан на http://code.activestate.com/recipes/134892/, но он считывает по одному символу за раз со стандартного ввода, что не будет работать, когда мой основной цикл считывает из него целые строки.

Вопрос

Есть ли способ в Python прослушивать нажатия клавиш, а также читать ввод по конвейеру?

Я заключил основную функцию в блок try, который исключает KeyboardInterrupt и печатает приятное небольшое сообщение на прощание вместо трассировки стека ошибок. Есть ли способ совместить это поведение с другим ключом?

Я бы предпочел не использовать мощный (по сравнению с моим небольшим скриптом) модуль, такой как pygame или tkinter, и вынужден использовать их основной цикл только для получения доступа к нажатиям клавиш. (также я не знаком с тем, как любой из них будет вести себя при получении ввода по каналу)


person rennat    schedule 01.11.2011    source источник


Ответы (1)


Самым простым решением было бы вообще не использовать трубу из хвоста. Придерживайтесь использования вашего стандартного ввода для пользовательского ввода и вместо этого напишите свой инструмент, чтобы он мог открывать и следовать за файлом, который вы хотите прочитать, без использования хвоста вообще. tail не очень сложный инструмент, если вы просто хотите переопределить эту его часть.

В качестве альтернативы вы можете создать именованный канал, который позволит вам введите в него хвост, и тогда ваша программа сможет прочитать его как файл и при этом иметь доступ к своему собственному стандартному вводу.

Если ни один из этих вариантов не подходит, я думаю, что лучше всего использовать отдельную библиотеку, которая напрямую опрашивает клавиатуру. Для справки, у pygame на самом деле нет «основного цикла», у него есть функция помпы событий, которую вы должны вызывать как можно чаще (в своем основном цикле), но если вы этого не сделаете, она не умрет. Он может буферизовать множество событий между насосами, и вы можете установить на нем фильтры, чтобы отбрасывать все события, которые вам не нужны, и оставлять только те, которые вы делаете (нажатия клавиш). Основная проблема с pygame заключается в том, что для такого простого инструмента требуется довольно тяжелая библиотека, поэтому я понимаю, что вы не решаетесь пойти по этому пути.

Да, и в качестве последнего варианта (наименее желательного, на мой взгляд) вы можете злоупотреблять механикой прерывания клавиатуры для создания «Emacs-подобных» клавишных аккордов. Например, нажмите Ctrl-C, затем Ctrl-(что угодно). Ctrl-C вызывает KeyboardInterrupt, затем в обработчике этого вы читаете следующий символ со стандартного ввода и что-то делаете с этим. Как только вы закончите, вернитесь к своей петле. Но это уродливо и хакерски, и я даже не уверен, будет ли это работать надежно.

person cecilkorik    schedule 01.11.2011
comment
Я никогда не видел именованные каналы, прежде чем я посмотрю на это. Также спасибо за разъяснения по pygame. - person rennat; 01.11.2011
comment
Причина, по которой я хотел использовать конвейерный ввод, заключается в том, что вы можете использовать его для быстрого выделения чего-либо. На самом деле я уже настроил его для выполнения любой команды, которую вы передаете ему после -- с popen, а затем использовать его вывод. Я надеялся также разрешить конвейерный ввод для универсальности. - person rennat; 01.11.2011
comment
Возможно, вы захотите взглянуть на это обсуждение. Похоже, что модуль curses может выполнять доступ к клавиатуре со значительно меньшей площадью, чем pygame. - person cecilkorik; 01.11.2011