2016/08/06(土) [n年前の日記]
#2 [python] Pythonで1文字だけキー入力ってどうやるんだろう
Raspberry Pi上のPythonスクリプトで、例えばカーソルキーを押すと、数字が増えたり減ったりするようなことをしたいなと。Windows上でも、Linux上でも、同じスクリプトで動作するなら尚嬉しい。
ググってみたら一般的には getch() なるものを使うようで、 _getch にそれらしいパッケージが。しかしコレは、pip install getch と打ってもインストールできない。なんだか大量にエラーが出る。
_py-getch なるパッケージもあった。 _joeyespo/py-getch: Portable getch() for Python. によると、pip install py-getch でインストールできて、以下のような感じで使えるらしい。
py-getch なら Windows10 x64 + Python 2.7.11上でインストールできたし、動作も確認できた。また、VMware + Ubuntu 16.04上でもインストールできた。
しかし、「1」「a」等のフツーのキーならともかく、カーソルキーを叩いた際に、妙な表示になる…。
_windows - Python method for reading keypress? - Stack Overflow でそれらしい記述が。コピペして動作確認。
ところが、このスクリプトを VMware + Ubuntu 16.04 LTS 上に持っていって動かすと、カーソルキーを押した瞬間に終了してしまう…。
おそらく、Windows上では 224,xxx という数字が返ってくるけど、Linux上では 27,xxx という数字が返ってきている、ような気がする。どちらかに特化した書き方をしないとダメなのだろうか…。
以下のようなスクリプトを書いて確認してみたり。
Windows10 x64 + cmd.exe上で、カーソルキーの、↑、↓、→、←を押すと、こうなる。
Ubuntu + bash上で、カーソルキーの、↑、↓、→、←を押すと、こうなる。
以下のような関係になってるのかな。
Windows は、0xe0 が届いた後、カーソルキーの種類を示すコードが届くけど、Linux では、0x1b,0x5b が届いた後、カーソルキーの種類を示すコードが届く、ということなのかなと。ただ、カーソルキーの種類を示すコードは、Windows と Linux では一致してないようで。
やはりどちらかに特化して書かないとダメかしらん。
ググってみたら一般的には getch() なるものを使うようで、 _getch にそれらしいパッケージが。しかしコレは、pip install getch と打ってもインストールできない。なんだか大量にエラーが出る。
_py-getch なるパッケージもあった。 _joeyespo/py-getch: Portable getch() for Python. によると、pip install py-getch でインストールできて、以下のような感じで使えるらしい。
from getch import getch, pause key = getch() print 'You pressed:', key pause()
py-getch なら Windows10 x64 + Python 2.7.11上でインストールできたし、動作も確認できた。また、VMware + Ubuntu 16.04上でもインストールできた。
しかし、「1」「a」等のフツーのキーならともかく、カーソルキーを叩いた際に、妙な表示になる…。
_windows - Python method for reading keypress? - Stack Overflow でそれらしい記述が。コピペして動作確認。
from getch import getch, pause print "Push any key. (ESC : exit)" while True: key = ord(getch()) if key == 27: # ESC print "ESC : exit." break elif key == 13: # Enter print "Enter" pass elif key == 224: # Special keys key = ord(getch()) if key == 80: print "Down Arrow" elif key == 72: print "Up Arrow" elif key == 75: print "Left Arrow" elif key == 77: print "Right Arrow" else: print "You pressed: %s (%d)" % (chr(key), key) if key == "x": print "exit." break pause()要するに、カーソルキー等の特殊なキーを叩いた場合は、「コレは特殊なキーだよ」と示すコードがまず1個届いて、その直後に「押されたキーは○○だよ」と示すコードが届くのだろうと。少なくとも Windows上では、このスクリプトでカーソルキーが押されてることを判別できた。
ところが、このスクリプトを VMware + Ubuntu 16.04 LTS 上に持っていって動かすと、カーソルキーを押した瞬間に終了してしまう…。
おそらく、Windows上では 224,xxx という数字が返ってくるけど、Linux上では 27,xxx という数字が返ってきている、ような気がする。どちらかに特化した書き方をしないとダメなのだろうか…。
以下のようなスクリプトを書いて確認してみたり。
from getch import getch, pause for i in range(20): key = getch() print "%d : 0x%02x" % (len(key), ord(key))
Windows10 x64 + cmd.exe上で、カーソルキーの、↑、↓、→、←を押すと、こうなる。
1 : 0xe0 1 : 0x48 1 : 0xe0 1 : 0x50 1 : 0xe0 1 : 0x4d 1 : 0xe0 1 : 0x4b
Ubuntu + bash上で、カーソルキーの、↑、↓、→、←を押すと、こうなる。
1 : 0x1b 1 : 0x5b 1 : 0x41 1 : 0x1b 1 : 0x5b 1 : 0x42 1 : 0x1b 1 : 0x5b 1 : 0x43 1 : 0x1b 1 : 0x5b 1 : 0x44
以下のような関係になってるのかな。
↑ | ↓ | → | ← | |
Windows | 0xe0 0x48 | 0xe0 0x50 | 0xe0 0x4d | 0xe0 0x4b |
Linux | 0x1b 0x5b 0x41 | 0x1b 0x5b 0x42 | 0x1b 0x5b 0x43 | 0x1b 0x5b 0x44 |
Windows は、0xe0 が届いた後、カーソルキーの種類を示すコードが届くけど、Linux では、0x1b,0x5b が届いた後、カーソルキーの種類を示すコードが届く、ということなのかなと。ただ、カーソルキーの種類を示すコードは、Windows と Linux では一致してないようで。
やはりどちらかに特化して書かないとダメかしらん。
[ ツッコむ ]
以上です。