はじめに
あまり需要はないのかもしれませんが,バックグラウンド実行中(つまり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
イベントハンドラを作成してあげることで,キーボード,マウスの入力がバックグラウンドで簡単に取れるようになります.
参考
- おもしろ雑感- pyHookについてコケたところ(http://d.hatena.ne.jp/favcastle/20120206/1328537612)
- <紙>さんLoG- msvcrt.kbhit() (http://jn1inl.blog77.fc2.com/blog-entry-2039.html)
- pythoncom crashes on KeyDown when used hooked to certain applications (https://stackoverflow.com/questions/26156633/pythoncom-crashes-on-keydown-when-used-hooked-to-certain-applications)