Реагирайте на ключови събития, докато вече четете от stdin в Python

Настройвам

Играх си със скрипт, за да насоча tail -f и да маркирам определени ключови думи. Не е голям проект, но нещо, което намирам за полезно.

В момента основният цикъл е основно:

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

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

Въпрос

Има ли начин в Python да слуша за натискания на клавиши, като същевременно чете въведени канали?

Увих основната функция в блок try, който изключва KeyboardInterrupt и отпечатва хубаво малко съобщение за сбогом вместо проследяване на стека за грешка. Има ли начин да се използва това поведение с друг ключ?

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


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


Отговори (1)


Най-простото решение би било изобщо да се избягва използването на тръба от опашката. Придържайте се към използването на вашия stdin за въвеждане от потребителя и вместо това напишете вашия инструмент, така че да може да отваря и следва файла, от който искате да четете, без изобщо да използвате опашка. tail не е ужасно сложен инструмент, ако просто искате да внедрите тази част от него.

Като алтернатива можете да създадете наименуван канал, който ще ви позволи да тръба опашка в него и след това вашата програма може да го чете като файл и все още да има достъп до собствения си stdin.

Ако нито една от тези опции не е опция, мисля, че изборът с отделна библиотека, която директно анкетира клавиатурата, може да е най-добрият ви залог. За протокола, pygame всъщност няма „главен цикъл“, той има функция за изпомпване на събития, която трябва да извиквате възможно най-често (в главния цикъл), но ако не го направите, няма да умре. Може да буферира много и много събития между помпите и можете да зададете филтри върху него, за да отхвърлите всички събития, които не ви интересуват, и да запазите само тези, които правите (натискания на клавиши). Основният проблем с pygame би бил, че това е доста тежка библиотека, за да се нуждае от такъв прост инструмент, така че разбирам вашето колебание да тръгнете по този път.

О, и като последна опция (по мое мнение най-малко желана) бихте могли да злоупотребите с механиката за прекъсване на клавиатурата, за да създадете "подобни на Emacs" клавишни акорди. Например, натиснете Ctrl-C, след това Ctrl-(каквото и да е). Ctrl-C извиква KeyboardInterrupt, след което в манипулатора за това четете следващия знак от stdin и правите нещо с него. След като приключите, върнете се към своя цикъл. Но това е грозно и хакерско и дори не съм сигурен дали ще работи надеждно.

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