Help us understand the problem. What is going on with this article?

Pythonでバックグラウンド実行中にキー入力を取得する(windows)

More than 3 years have passed since last update.

はじめに

あまり需要はないのかもしれませんが,バックグラウンド実行中(つまりPythonアプリにフォーカスがあっていない状態)のキー入力を取得したい時が稀にあります.JavaにはJNativeHookというライブラリがあり使い勝手もそこそこ良いのですが,それだけのためにJavaを使うのもな,,,,と思いPythonでやる方法を模索した結果,どん詰まりしたので備忘録を残しておきます.

環境

  • Windows8 (10)
  • Python3.6.0

PyHookなるものがあるものの...

まず調べて色々なところで引っかかったのが,PyHookを使う方法.
バックグラウンドで動いて,キーダウン,キーアップ等のイベントがとれるらしい(おもしろ雑感- pyHookについてコケたところ).

早速試してみようと,http://www.lfd.uci.edu/~gohlke/pythonlibs からpyHookの対応するバージョンを落としてきて,

wheel install pyHook‑1.5.1‑cp36‑cp36m‑win_amd64.whl

でインストール(バージョン問題等で非常に手間取った).

from pyHook import HookManager
from win32gui import PumpMessages, PostQuitMessage

class Keystroke_Watcher(object):
    def __init__(self):
        self.hm = HookManager()
        self.hm.KeyDown = self.on_keyboard_event
        self.hm.HookKeyboard()


   def on_keyboard_event(self, event):
        try:
            print ('MessageName:',event.MessageName)
            print ('Ascii:', repr(event.Ascii), repr(chr(event.Ascii)))
            print ('Key:', repr(event.Key))
            print ('KeyID:', repr(event.KeyID))
            print ('ScanCode:', repr(event.ScanCode))
            print ('Time:',event.Time)
            print ('-'*5)
        finally:
            return True

   def your_method(self):
        pass

   def shutdown(self):
        PostQuitMessage(0)
        self.hm.UnhookKeyboard()


watcher = Keystroke_Watcher()
PumpMessages()

を実行してみたものの,Emacs, SublimeTextを使っているときは問題なく動くが,chromeブラウザ上でキーを叩くと落ちるという謎事態に.エラーとしては

TypeError: KeyboardSwitch() missing 8 required positional arguments: 'msg', 'vk_code', 'scan_code', 'ascii', 'flags', 'time', 'hwnd', and 'win_name'

のようなもので,調べていったっ結果,どうやらPython3系にて実行した時に発生するバグらしく(https://stackoverflow.com/questions/26156633/pythoncom-crashes-on-keydown-when-used-hooked-to-certain-applications ),お手上げ状態.

PyHooked

なにかいい代替手段が見つからないかさがしていたところ,pyHookedなるものをみつけました.
インストールは

pip install pyhooked

で行い,Githubページのexample.pyにあるように,

from pyhooked import Hook, KeyboardEvent, MouseEvent


def handle_events(args):
    if isinstance(args, KeyboardEvent):
        print(args.key_code, args.current_key, args.event_type)

    if isinstance(args, MouseEvent):
        print(args.mouse_x, args.mouse_y)

hk = Hook()  # make a new instance of PyHooked
hk.handler = handle_events  # add a new shortcut ctrl+a, or triggered on mouseover of (300,400)
hk.hook()  # hook into the events, and listen to the presses

イベントハンドラを作成してあげることで,キーボード,マウスの入力がバックグラウンドで簡単に取れるようになります.

参考

xcoo
ゲノムおよび生体情報解析のトータルソリューション「Chrovis」の開発をしています。
https://xcoo.co.jp
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away