web-dev-qa-db-ja.com

Linuxマシンのpython 3でキーの押下を検出する最も簡単な方法は何ですか?

現在、Raspberry Piとmakey makeyを使用して小さなコードを作成しようとしています。 makey makeyは、特定の接点に電力が供給されているときにUSBキーボードとして機能する小さなボードです。私の質問は、pythonスクリプト内でこれらのキープレスを検出する最も簡単な方法は何ですか。GPIOピンを使用する方が簡単だと理解していますが、今はこれを探しています。例を見てきたたとえば、msvcrtからgetch()を使用する(私が理解しているのはWindowsのみです)、pygame.keyを使用する、getKeyを使用するなどです。どれが最も使いやすいですか?押されているキーとキーを検出できるものはありますか?解放されますか?

疑似コードコード(...それは何と呼ばれているのですか?)

import whatever needs importing    

if the "W" key is pressed:
   print ("You pressed W")

Elif the "S" is pressed:
    print ("You pressed S")

等々。ありがとう。

11
montainz09

これは、stdinをrawモードにして(バッファリングを無効にするため、Enterキーを押す必要がない)単一の文字を取得する単純なループです。あなたはもっと賢い何かをするべきです(それを無効にするためのwithステートメントのような)しかしあなたはここでアイデアを得ます:

import tty
import sys
import termios

orig_settings = termios.tcgetattr(sys.stdin)

tty.setcbreak(sys.stdin)
x = 0
while x != chr(27): # ESC
    x=sys.stdin.read(1)[0]
    print("You pressed", x)

termios.tcsetattr(sys.stdin, termios.TCSADRAIN, orig_settings)    

Pythonの主要なリリースを検出するにはループする必要があると思います。

ETAもう少し説明:

Linuxでは、プログラムへの入力はline bufferedになります。これは、オペレーティングシステムが1行になるまで入力をバッファリングすることを意味します。そのため、ユーザーが「Enter」を押すまで、プログラムはユーザーが入力したものすら何も表示しません。言い換えれば、プログラムがユーザーに「w」と入力することを期待していて、ユーザーがこれを行う場合、「w」は、ユーザーが「Enter」を押すまでOSのバッファーにとどまります。この時点で、行全体がプログラムに配信されるため、ユーザーの入力として文字列「w\n」を取得します。

Ttyをrawモードにすることで、これを無効にできます。これを行うには、Python function tty.setcbreak]を使用します。これにより、Linuxのttyドライバーが呼び出され、バッファリングを停止するように指示されます。sys.stdin引数をバッファリングをオフにしたいストリームを教えてください1。したがって、tty.setcbreak呼び出しの後、上記のループは、ユーザーが押すすべてのキーの出力を提供します。

ただし、複雑なのは、いったんプログラムが終了しても、ttyがまだrawモードになっていることです。現代の端末設定が提供する能力(コントロールやエスケープシーケンスを使用する場合など)が得られないため、これは一般的に満足できないものです。たとえば、ctrl-Cを使用してプログラムを終了できない場合があることに注意してください。したがって、入力文字の読み取りが完了したら、端末をcookedモードに戻す必要があります。 termios.tcsetattr呼び出しは、単に「ターミナルを私が見つけた方法で元に戻す」と言います。これは、プログラムの最初に「端末の現在の設定をすべて教えて」と言っているtermios.tcgetattrを最初に呼び出すことで、これを行う方法を知っています。

これらをすべて理解したら、プログラムに適した関数に機能を簡単にカプセル化できるはずです。

1 stdinは、ユーザーから入力が送られるストリームです。ウィキペディアは 標準ストリーム について詳しく教えてくれます。

16
Turn

良い軽量モジュール curtsies を使用すると、次のようなことができます(examples /ディレクトリから取得):

from curtsies import Input

def main():
    with Input(keynames='curses') as input_generator:
        for e in input_generator:
            print(repr(e))

if __name__ == '__main__':
    main()

キーボードのキーを押すと、次のようになります。

'a'
's'
'KEY_F(1)'
'KEY_F(2)'
'KEY_F(3)'
'KEY_F(4)'
'KEY_F(5)'
'KEY_LEFT'
'KEY_DOWN'
'KEY_UP'
'KEY_RIGHT'
'KEY_NPAGE'
'\n'

curtsiesは bpython によって、端末関連のものの低レベルの抽象化として使用されます。

入力をデコードする基本的な問題は、xtermgnome-terminalsのような異なる端末や端末エミュレータープログラムでは、物理的に同じキーが異なるキーコードシーケンスを生成することです。そのため、入力をデコードするために使用する端末設定を知る必要があります。このようなモジュールは、これらの残酷な詳細から抽象化するのに役立ちます。

11
user3159253