Znajdowanie wartości klawiszy strzałek w Pythonie: dlaczego są one potrójne?

Próbuję znaleźć wartości, które mój lokalny system przypisuje klawiszom strzałek, szczególnie w Pythonie. Używam do tego poniższego skryptu:

import sys,tty,termios
class _Getch:       
    def __call__(self):
            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

def get():
    inkey = _Getch()
    while(1):
            k=inkey()
            if k!='':break
    print 'you pressed', ord(k)

def main():
    for i in range(0,25):
        get()

if __name__=='__main__':
    main()

Potem uruchomiłem skrypt i wcisnąłem w górę w dół w prawo w lewo, co dało mi to wyjście:

$ python getchar.py 
you pressed 27
you pressed 91
you pressed 65
you pressed 27
you pressed 91
you pressed 66
you pressed 27
you pressed 91
you pressed 67
you pressed 27
you pressed 91
you pressed 68

Jest to anomalne, ponieważ sugeruje, że klawisze strzałek są zarejestrowane jako potrójna (27-91-6x) w moim systemie, ponieważ każde naciśnięcie klawisza zajmuje trzy instancje get (). Dla porównania, naciśnięcie a, b, c i CTRL-C daje:

you pressed 97
you pressed 98
you pressed 99
you pressed 3

Czy ktoś może mi wyjaśnić, dlaczego wartości moich strzałek wydają się być przechowywane jako potrójne? Dlaczego tak jest? Czy to jest takie samo na wszystkich platformach? (Używam Debiana Linux.) Jeśli nie, w jaki sposób powinienem zachować wartości klawiszy strzałek?

Celem końcowym jest to, że próbuję napisać program, który musi poprawnie rozpoznać klawisze strzałek i wykonać funkcję w zależności od tego, który klawisz strzałek został naciśnięty.

Author: Zero Piraeus, 2014-03-14

2 answers

Myślę, że to rozgryzłem.

Dowiedziałem się z tutaj {[18] } że każdy klawisz strzałki jest reprezentowany przez unikalny kod ucieczki ANSI. Potem dowiedziałem się, że kody ucieczki ANSI różnią się w zależności od systemu i aplikacji: w moim terminalu naciśnięcie cat i naciśnięcie strzałki w górę daje ^[[A, w C wydaje się być \033[A, itd. Ta ostatnia część, [A, pozostaje taka sama, ale kod poprzedzający Escape może być szesnastkowy (rozpoczynający się od x), ósemkowy (zaczynający się od 0) lub dziesiętny (bez ołowiu w liczba).

Następnie otworzyłem konsolę Pythona i podłączyłem trzyosobowe, które wcześniej otrzymałem, próbując znaleźć ich wartości znaków. Jak się okazało, chr(27) dał \x1b, chr(91) podałem [, A wywołanie chr na 65,66,67,68 zwróciło A,B,C,D odpowiednio. Wtedy było jasne: \x1b był Kod ucieczki!

Następnie zauważyłem, że klawisz strzałki, w ANSI reprezentowany jako potrójny, jest oczywiście reprezentowany jako trzy znaki, więc musiałem zmienić mój kod tak, aby czytać w trzech znakach na czas. Oto wynik:

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

def get():
        inkey = _Getch()
        while(1):
                k=inkey()
                if k!='':break
        if k=='\x1b[A':
                print "up"
        elif k=='\x1b[B':
                print "down"
        elif k=='\x1b[C':
                print "right"
        elif k=='\x1b[D':
                print "left"
        else:
                print "not an arrow key!"

def main():
        for i in range(0,20):
                get()

if __name__=='__main__':
        main()
 28
Author: Newb,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:54:38

Używam Maca i użyłem poniższego kodu i działało dobrze: Mam wartości dla moich klawiszy strzałek jako 0,1,2,3 (Góra, Dół, Lewo, Prawo): Zawsze dobrze zapamiętać kod 27 dla klucza ESC. Pozdrawiam!

while True:
    key = cv2.waitKey(1) & 0xFF

    # if the 'ESC' key is pressed, Quit
    if key == 27:
        quit()
    if key == 0:
        print "up"
    elif key == 1:
        print "down"
    elif key == 2:
        print "left"
    elif key == 3:
        print "right"
    # 255 is what the console returns when there is no key press...
    elif key != 255:
        print(key)
 3
Author: Mauricio Alo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-09-08 20:06:40