Pythonでキー押下を検出しますか?


103

私はpythonでストップウォッチタイプのプログラムを作成していて、キーが押されたかどうかを検出する方法を知りたい(一時停止のpや停止のsなど)、それを待つraw_inputのようなものにしたくない実行を続行する前のユーザーの入力。誰でもこれをwhileループで行う方法を知っていますか?

また、このクロスプラットフォームを作成したいのですが、それが不可能な場合、私の主な開発ターゲットはlinuxです


OS Xの場合stackoverflow.com/a/47197390/5638869はPython 2および3で動作します
neoDev

回答:


69

Pythonには、多くの機能を備えたキーボードモジュールがあります。おそらく次のコマンドでインストールしてください:

pip3 install keyboard

次に、次のようなコードで使用します。

import keyboard  # using module keyboard
while True:  # making a loop
    try:  # used try so that if user pressed other than the given key error will not be shown
        if keyboard.is_pressed('q'):  # if key 'q' is pressed 
            print('You Pressed A Key!')
            break  # finishing the loop
    except:
        break  # if user pressed a key other than the given key the loop will break

1
Linuxについてはわかりませんが、Windowsでは動作します。

71
keyboardどうやらLinuxでrootが必要:/
Inaimathi 2017年

このソリューションを試しましたが、インストール後にモジュールをインポートしようとすると、「ImportError: 'keyboard'という名前のモジュールがありません」というメッセージが表示され、機能しませんでした。GitHubリポジトリをチェックインしたところ、関連する問題が見つかりましが、問題は解決しませんでした。次に、リポジトリをダウンロードしていくつかの例を実行してみましたが、@ Inaimathiが以前にコメントしたように、「ImportError:このライブラリをLinuxで使用するにはrootでなければなりません」というメッセージが表示されます。どうやらPythonでキーボードを管理するための完全なモジュールのようですが、ルートの要件は大きな欠如です:(
Ivanhercaz

3
「Xに依存しないようにするために、Linuxパーツはrawデバイスファイル(/ dev / input / input *)を読み取りますが、これにはルートが必要です。」
jrouquie

7
なぜ試してみるのかわかりません。
TypicalHog 2018

49

Windowsを使用していて、有効な答えを見つけるのに苦労していた人のために、私はここにあります。

from pynput.keyboard import Key, Listener

def on_press(key):
    print('{0} pressed'.format(
        key))

def on_release(key):
    print('{0} release'.format(
        key))
    if key == Key.esc:
        # Stop listener
        return False

# Collect events until released
with Listener(
        on_press=on_press,
        on_release=on_release) as listener:
    listener.join()

上記の関数は、「esc」キーを放すと、押しているキーに加えてアクションを開始します。キーボードのドキュメントは、より多様な使用法についてはこちらです。

Markus von Broadyは、潜在的な問題を次のように強調しました:この回答では、このスクリプトをアクティブにするために現在のウィンドウにいる必要はありません。

from win32gui import GetWindowText, GetForegroundWindow
current_window = (GetWindowText(GetForegroundWindow()))
desired_window_name = "Stopwatch" #Whatever the name of your window should be

#Infinite loops are dangerous.
while True: #Don't rely on this line of code too much and make sure to adapt this to your project.
    if current_window == desired_window_name:

        with Listener(
            on_press=on_press,
            on_release=on_release) as listener:
            listener.join()

7
@ nimig18 ...そしてルートは必要ありません:)
cz

1
このソリューションには問題があります(代替案については不明です)。キーを有効にするために、コンソールウィンドウ内でキーを押す必要はありません。ESCが押されるまでなんらかの処理を実行するスクリプトがあり、その後別のプログラムでそれを押すと想像してください。
Markus von Broady

1
@MarkusvonBroady win32guiでそれを解決するのに十分だと思います。少なくともWindowsユーザーにとっては解決できるように私の回答を編集しました。
Mitrek、

@Mitrek私はこれを試しましたが、私のコードはそれ以上の実行を停止し、ここで止まっています。input()のように機能します。私はコードをセレン、firefoxで実行していますが、このシーケンスに遭遇するとすぐに、それ以上のアクションはありません。
Lakshmi Narayanan

1
LinuxとWindowsの両方で機能するため、受け入れられた答えである必要があります
Akash Karnatak

31

OPがraw_inputについて言及しているように、これはCLIソリューションが必要であることを意味します。Linux:cursesは必要なものです(Windows PDCurses)。CursesはcliソフトウェアのグラフィカルAPIであり、キーイベントを検出するだけではありません。

このコードは、新しい行が押されるまでキーを検出します。

import curses
import os

def main(win):
    win.nodelay(True)
    key=""
    win.clear()                
    win.addstr("Detected key:")
    while 1:          
        try:                 
           key = win.getkey()         
           win.clear()                
           win.addstr("Detected key:")
           win.addstr(str(key)) 
           if key == os.linesep:
              break           
        except Exception as e:
           # No input   
           pass         

curses.wrapper(main)

これは本当にいいです。それに遭遇する前に永遠に検索しなければならなかった。ハッキングtermiosなどを行うよりもはるかにクリーンなようです...
Hugh Perkins

5
import os終了してサンプルを終了できるようにするために追加する必要がありました。
モルト2017

win.nodelay(False)代わりに実行するとTrue、毎秒100万の例外が生成されません。
Johannes Hoff

24

keyboardモジュールでできることはもっとあります。

ここにいくつかの方法があります:


方法1:

関数の使用read_key()

import keyboard

while True:
    if keyboard.read_key() == "p":
        print("You pressed p")
        break

これは、キーpが押されたときにループを解除するつもりです。


方法#2:

関数の使用wait

import keyboard

keyboard.wait("p")
print("You pressed p")

pコードが押されるのを押して続行するのを待ちます。


方法#3:

関数の使用on_press_key

import keyboard

keyboard.on_press_key("p", lambda _:print("You pressed p"))

コールバック関数が必要です。_キーボード関数がキーボードイベントをその関数に返すため、使用しました。

実行すると、キーが押されたときに関数が実行されます。次の行を実行すると、すべてのフックを停止できます。

keyboard.unhook_all()

方法#4:

この方法は、すでにuser8167727によって回答されていますが、私が彼らが作成したコードには同意しません。関数を使用しますis_pressedが、別の方法で:

import keyboard

while True:
    if keyboard.is_pressed("p"):
        print("You pressed p")
        break

p押すとループが切れます。


ノート:

  • keyboard OS全体からキープレスを読み取ります。
  • keyboard Linuxでrootが必要

11
キーボードモジュールを使用する最大の欠点は、ROOTユーザーとして実行するという要件です。これにより、モジュールがコード内で冗長になります。キーが押されたかどうかをポーリングするだけでは、root権限は必要ありません。私はドキュメントを読み、制限がモジュールに存在する理由を理解しましたが、必要なのがキーをポーリングすることだけである場合は他の場所を調べます...
muman

非常に役立つ情報を共有しました。1 keyboard.wait()つ以上のキーを待ち、どちらかが押されても続行できるかどうかを知りたいと思った
Preetkaran Singh

@PreetkaranSingh wait()はこの機能を提供しません。keyboard.read_key()whileループにパックされたif条件で使用する必要があります。方法1を参照してください
Black Thunder

ありがとうございます!、でのsuppressキーワードの使用法、使用するkeyboard.read_key()場合と使用しない場合
について少し説明し

@PreetkaranSingh私はそうするつもりですが、抑圧論について十分な情報を持っていません
Black Thunder

13

以下のためにWindowsのあなたは使用することができmsvcrt、このように:

   import msvcrt
   while True:
       if msvcrt.kbhit():
           key = msvcrt.getch()
           print(key)   # just to show the result

7
msvcrtはWindows専用のモジュールです。
Dunatotatos

1
私は実際にpynputを使用していますが、それがより良い答えになるかもしれません
Benjie

OS X(Linuxについて知らない)で動作するPynputは、動作するためにrootとして実行する必要があることに注意してください。それは一部の人々にとってはスターターではないかもしれません。
Gabe Weiss、

質問は「クロスプラットフォーム」または「linux」に対するものだと誓ったかもしれない...
アーロン・マン

10

このコードを使用して、押されたキーを見つけます

from pynput import keyboard

def on_press(key):
    try:
        print('alphanumeric key {0} pressed'.format(
            key.char))
    except AttributeError:
        print('special key {0} pressed'.format(
            key))

def on_release(key):
    print('{0} released'.format(
        key))
    if key == keyboard.Key.esc:
        # Stop listener
        return False

# Collect events until released
with keyboard.Listener(
        on_press=on_press,
        on_release=on_release) as listener:
    listener.join()

ただし、ここでは、macOSを使用し、pynputとキーボードの両方を個別にインストールしました。プログラムはエラーなしで実行されますが、(Pythonシェルで)特別なキーしか検出できません。英数字キーは検出されず、逆に、シェルでコードを書いているかのように見なされます。問題が何であるか知っていますか?
Dario DenizErgün19年

シェルで同じコードが機能しました。これをチェックしてください。キーボードパッケージはこのコードを必要としません。
Manivannan Murugavel

1
キーボードのlibにはrootが必要なので、これはLinuxで使用する方法です。
David

1
このソリューションはすべてのキーストロークを検出ます。また、別の端末ウィンドウで発生するものもあります。残念ながら、これは可能な使用例を厳しく制限します。
Serge Stroobandt、

6

PyGameを使用してウィンドウを表示すると、主要なイベントを取得できます。

手紙の場合p

import pygame, sys
import pygame.locals

pygame.init()
BLACK = (0,0,0)
WIDTH = 1280
HEIGHT = 1024
windowSurface = pygame.display.set_mode((WIDTH, HEIGHT), 0, 32)

windowSurface.fill(BLACK)

while True:
    for event in pygame.event.get():
        if event.key == pygame.K_p: # replace the 'p' to whatever key you wanted to be pressed
             pass #Do what you want to here
        if event.type == pygame.locals.QUIT:
             pygame.quit()
             sys.exit()

2

そこで、この投稿に基づいてゲームの種類を作成しました(msvcrライブラリとPython 3.7を使用)。

以下は、押されたキーを検出するゲームの「主な機能」です。

# Requiered libraries - - - -
import msvcrt
# - - - - - - - - - - - - - -


def _secret_key(self):
    # Get the key pressed by the user and check if he/she wins.

    bk = chr(10) + "-"*25 + chr(10)

    while True:

        print(bk + "Press any key(s)" + bk)
        #asks the user to type any key(s)

        kp = str(msvcrt.getch()).replace("b'", "").replace("'", "")
        # Store key's value.

        if r'\xe0' in kp:
            kp += str(msvcrt.getch()).replace("b'", "").replace("'", "")
            # Refactor the variable in case of multi press.

        if kp == r'\xe0\x8a':
            # If user pressed the secret key, the game ends.
            # \x8a is CTRL+F12, that's the secret key.

            print(bk + "CONGRATULATIONS YOU PRESSED THE SECRET KEYS!\a" + bk)
            print("Press any key to exit the game")
            msvcrt.getch()
            break
        else:
            print("    You pressed:'", kp + "', that's not the secret key(s)\n")
            if self.select_continue() == "n":
                if self.secondary_options():
                    self._main_menu()
                break

ポーグラムの完全なソースコードが必要な場合は、それを表示するか、ここからダウンロードできます。

秘密の鍵ゲーム(GitHub)

(注:秘密のキープレスはCtrl+ですF12

この情報を参考にご覧になりたい方のために、参考にしていただければ幸いです。



1
key = cv2.waitKey(1)

これはopenCVパッケージからのものです。待機せずにキープレスを検出します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.