Python `keyboard` ライブラリ徹底解説!キーボード操作を自由自在に操る 🐍⌨️

Pythonを使っていると、「キーボード操作を自動化したい」「特定のキーが押されたら処理を実行したい」と思うことはありませんか? 🤔 そんな時に非常に役立つのが keyboard ライブラリです。

このライブラリは、Windows、Linux、そして実験的ではありますがmacOS上で、グローバルなキーボードイベントの監視(フック)キー入力のシミュレーションホットキーの登録などを可能にする、強力ながらもシンプルなPythonライブラリです。特別なCモジュールをコンパイルする必要がなく、依存関係もないため、手軽に導入できるのが魅力です。

このブログ記事では、keyboard ライブラリの基本的な使い方から、少し応用的な機能、そして利用する上での注意点まで、幅広く、そして深く解説していきます。この記事を読めば、あなたもkeyboardライブラリを使いこなし、Pythonでのキーボード操作をマスターできるはずです! 💪

対象読者としては、以下のような方を想定しています。

  • Pythonでキーボード操作を自動化したい方
  • 特定のキー入力に反応するプログラムを作りたい方
  • keyboard ライブラリの機能や使い方を詳しく知りたい方
  • GUI操作の自動化(RPA)に興味がある方

さあ、keyboard ライブラリの世界へ飛び込みましょう!🚀

keyboard ライブラリを使用するには、まずインストールが必要です。pipを使って簡単にインストールできます。ターミナル(コマンドプロンプト)を開き、以下のコマンドを実行してください。

pip install keyboard

これでインストールは完了です。依存ライブラリはないため、これだけで準備OKです。

🚨 重要な注意点:実行権限について 🚨

keyboard ライブラリは、OSレベルでキーボード入力を監視・操作するため、多くの場合、管理者権限(root権限)が必要になります。これはセキュリティ上の理由からです。

  • Windows: スクリプトを実行する際に、コマンドプロンプトやPowerShellを「管理者として実行」する必要があります。
  • Linux: スクリプトを実行する際に、sudo コマンドを使用する必要があります。
    sudo python your_script.py
    もし管理者権限なしで実行しようとすると、ImportError: You must be root to use this library on linux. のようなエラーが発生します。
  • macOS: keyboard ライブラリのmacOSサポートは実験的な段階です(2021年9月時点の情報)。また、動作させるためには、スクリプトを実行するターミナルやIDE(統合開発環境)などのアプリケーションに対して、「システム環境設定」>「セキュリティとプライバシー」>「プライバシー」>「アクセシビリティ」で、コンピュータの制御を許可する必要があります。設定後も sudo での実行が必要になる場合があります。macOS環境では、より安定している pynput ライブラリの使用も検討する価値があります。
警告: 管理者権限でプログラムを実行することは、セキュリティリスクを伴います。信頼できないスクリプトを実行しないように、細心の注意を払ってください。

基本的なインポート

スクリプト内でkeyboardライブラリを使用するには、まずインポートします。

import keyboard

これで、ライブラリの様々な機能を使う準備が整いました!🎉

keyboard ライブラリの核となる機能を見ていきましょう。

1. キー入力の検知 (イベントフック)

ユーザーがどのキーを押したり離したりしたかをリアルタイムで検知できます。これは「フック (Hooking)」と呼ばれます。

`keyboard.hook()` を使う方法

すべてのキーボードイベント(押下・解放)を捕捉し、指定したコールバック関数を実行します。

import keyboard

# キーイベントが発生したときに呼び出される関数
def on_key_event(event):
    print(f'イベントタイプ: {event.event_type}, キー名: {event.name}, スキャンコード: {event.scan_code}, 時間: {event.time}')
    # 'esc' キーが押されたらフックを解除してプログラム終了
    if event.name == 'esc' and event.event_type == keyboard.KEY_DOWN:
        print('ESCキーが押されたので終了します。')
        keyboard.unhook_all() # すべてのフックを解除
        return False # フックを止める場合 False を返す (必須ではない)

# グローバルキーボードフックを設定
keyboard.hook(on_key_event)

print("キーボードイベントの監視を開始しました。ESCキーで終了します。")

# プログラムが終了しないように待機 (他の処理があれば不要)
# keyboard.wait() は内部でフックを使っているので、ここでは単純なループなどで待機
# もしくは、keyboard.wait('esc') を使っても良いが、その場合は hook 解除のロジックが変わる
try:
    keyboard.wait() # 何らかの方法でプログラムを待機させる必要がある
except KeyboardInterrupt:
    print("\nCtrl+Cにより終了します。")
finally:
    # 念のため最後にフックを解除
    keyboard.unhook_all()

keyboard.hook() に渡すコールバック関数は、引数として KeyboardEvent オブジェクトを受け取ります。このオブジェクトには以下の属性が含まれます。

  • event_type: イベントの種類 (keyboard.KEY_DOWN または keyboard.KEY_UP)。
  • name: キーの名前(例: ‘a’, ‘space’, ‘ctrl’, ‘esc’)。小文字で表現されます。
  • scan_code: キーボード上の物理的な位置を示すスキャンコード(数値)。
  • time: イベントが発生したタイムスタンプ。
  • device: イベントが発生したデバイス名(Windowsでは None になることがあります)。
  • is_keypad: キーがテンキー(数値パッド)上のものかどうかを示すブール値。
  • modifiers: イベント発生時に押されていた修飾キー(Shift, Ctrlなど)のリスト。

`keyboard.on_press()`, `keyboard.on_release()` を使う方法

キーが押された時だけ、または離された時だけ反応させたい場合に便利です。

import keyboard

def on_press_a(event):
    # event 引数は渡されるが、使わない場合はアンダースコア(_)で受ける慣習もある
    print("'a' キーが押されました!")

def on_release_space(event):
    print("スペースキーが離されました!")

# 'a' キーが押されたときのコールバックを登録
# trigger_on_release=True にすると、キーを離した時に発火する
keyboard.on_press_key('a', on_press_a)

# 'space' キーが離されたときのコールバックを登録
keyboard.on_release_key('space', on_release_space)

print("'a'キーを押すか、スペースキーを離すとメッセージが表示されます。ESCキーで終了します。")

# 'esc' キーが押されるまでプログラムを待機
keyboard.wait('esc')

# 登録したフックを解除(個別に解除も可能)
# keyboard.remove_hotkey(on_press_a) # ハンドラ関数を指定して削除
keyboard.unhook_all()
print("フックを解除しました。")

on_press_keyon_release_key を使うと、特定のキーに対する処理を簡潔に記述できます。

`keyboard.wait()`

特定のキーが押されるまでプログラムの実行をブロック(待機)します。内部的にはキーボードフックを使用しています。

import keyboard

print("プログラムを開始しました。'enter' キーを押すと次に進みます。")
keyboard.wait('enter')

print("'enter' キーが押されました!")
print("次は 'q' キーを押すと終了します。")
keyboard.wait('q')

print("'q' キーが押されたのでプログラムを終了します。")

2. キーの送信 (シミュレーション)

プログラムからキーボード入力をシミュレートすることができます。定型文の入力や操作の自動化に便利です。

`keyboard.press_and_release()` / `keyboard.send()`

指定したキーを押してすぐに離す動作をシミュレートします。最もよく使われる関数の一つです。send()press_and_release() のエイリアス(別名)のようなものです。

import keyboard
import time

print("5秒後に 'Hello Python!' と入力します...")
time.sleep(5)

# 'H' (Shift + h) を入力
keyboard.press_and_release('shift+h')
# 'e', 'l', 'l', 'o' を入力
keyboard.press_and_release('e')
keyboard.press_and_release('l')
keyboard.press_and_release('l')
keyboard.press_and_release('o')
# スペースを入力
keyboard.press_and_release('space')
# 'P' (Shift + p) を入力
keyboard.send('shift+p') # send() も同じ動作
# 'y', 't', 'h', 'o', 'n' を入力
keyboard.send('y')
keyboard.send('t')
keyboard.send('h')
keyboard.send('o')
keyboard.send('n')
# '!' (Shift + 1) を入力
keyboard.send('shift+1')

print("入力が完了しました。")

キー名の指定には、'a', 'b' などの文字キー、'space', 'enter', 'tab', 'esc', 'f1', 'left', 'ctrl', 'alt', 'shift', 'win' (Windowsキー) / 'cmd' (macOS Commandキー) などの特殊キー名が使えます。 修飾キーとの組み合わせは '+' で繋ぎます(例: 'ctrl+c', 'alt+tab', 'shift+a')。 複数のキーシーケンスを一度に送る場合は ',' で区切ります(例: 'alt+f, e' -> Alt+Fを押した後、Eを押す)。

`keyboard.write()`

文字列をタイプライターのように一文字ずつ入力します。 Shiftキーの押し下げも自動で行われます。

import keyboard
import time

print("5秒後にメッセージを入力します...")
time.sleep(5)

text_to_write = "こんにちは、Keyboardライブラリです! 😉"
keyboard.write(text_to_write, delay=0.05) # delay で文字間の入力遅延を設定(秒)

print("入力が完了しました。")

delay 引数を調整することで、より自然な入力速度に見せかけることも可能です。

`keyboard.press()` と `keyboard.release()`

キーを押し続ける、または離す動作を個別に制御したい場合に使います。例えば、Shiftキーを押しながら複数のキーを入力する、といった操作が可能です。

import keyboard
import time

print("5秒後に Shift を押しながら 'abc' を入力し、Shift を離します...")
time.sleep(5)

keyboard.press('shift') # Shiftキーを押し続ける
time.sleep(0.1) # 少し待機
keyboard.press_and_release('a')
time.sleep(0.1)
keyboard.press_and_release('b')
time.sleep(0.1)
keyboard.press_and_release('c')
time.sleep(0.1)
keyboard.release('shift') # Shiftキーを離す

print("操作が完了しました。 (ABCと入力されたはず)")

3. ホットキーの登録

特定のキーの組み合わせ(ホットキー)が押されたときに、指定した関数(コールバック関数)を実行するように登録できます。アプリケーションのショートカットキー作成などに非常に便利です。

`keyboard.add_hotkey()`

import keyboard
import datetime
import sys # プログラム終了のため

def show_current_time():
    now = datetime.datetime.now()
    print(f"現在の時刻: {now.strftime('%Y-%m-%d %H:%M:%S')}")

def quit_program():
    print("Ctrl+Alt+Q が押されたのでプログラムを終了します。")
    keyboard.unhook_all() # 念のためフック解除
    sys.exit() # プログラム終了

# Ctrl + Shift + T が押されたら show_current_time 関数を実行
# args でコールバック関数に渡す引数をタプルで指定できる (今回は未使用)
keyboard.add_hotkey('ctrl+shift+t', show_current_time)

# Ctrl + Alt + Q が押されたら quit_program 関数を実行
keyboard.add_hotkey('ctrl+alt+q', quit_program)

# 複数のキーシーケンスも可能 (PageUpを押してからPageDownを押す)
def type_foobar():
    print("PageUp -> PageDown ホットキーが押されました! 'foobar'と入力します。")
    # ホットキーのコールバック内で write を使う場合は少し待機した方が安全な場合がある
    keyboard.call_later(lambda: keyboard.write('foobar'), delay=0.1)

keyboard.add_hotkey('page up, page down', type_foobar, trigger_on_release=True) # キーを離した時に発火

print("ホットキーが登録されました。")
print("- Ctrl+Shift+T で現在時刻を表示")
print("- PageUp -> PageDown で 'foobar' と入力")
print("- Ctrl+Alt+Q でプログラム終了")

# プログラムを待機させる (イベントループを開始)
keyboard.wait() # この wait は内部でイベントを処理し続ける

# 通常は wait() から抜けないが、quit_program で抜けた場合など
print("プログラムが終了しました。")

add_hotkey() は非常に強力で、複雑なキーの組み合わせや、複数のステップからなるキーシーケンスも登録できます。 trigger_on_release=True を指定すると、ホットキーの最後のキーが離されたときにコールバックが実行されます。デフォルトは False で、押された瞬間に実行されます。

登録したホットキーは keyboard.remove_hotkey(hotkey_or_handler)keyboard.unhook_all_hotkeys() で解除できます。

`keyboard.add_abbreviation()` (非推奨の可能性あり?)

ドキュメントやいくつかの情報源には、特定の文字列を入力した後にスペースキーなどを押すと、別の文字列に置換する「略語展開」機能 add_abbreviation() が記載されています。

import keyboard

# '@@' と入力してスペースを押すとメールアドレスに置換する (と想定される機能)
# keyboard.add_abbreviation('@@', 'my.long.email@example.com')

# 'btw' と入力してスペースを押すと 'by the way' に置換する (と想定される機能)
# keyboard.add_abbreviation('btw', 'by the way')

print("略語展開が設定されました(もし機能が存在すれば)。")
print("例: '@@' + スペース, 'btw' + スペース")
print("ESCキーで終了します。")

keyboard.wait('esc')
注意: add_abbreviation 機能は、ライブラリのバージョンや環境によっては意図した通りに動作しない、あるいは非推奨となっている可能性があります。ホットキー機能 (add_hotkey) を使って同様の機能を実現する方が確実かもしれません。

keyboard ライブラリには、さらに便利な高度な機能も用意されています。

1. キーボード操作の記録と再生

一連のキーボード操作を記録し、後でそれを再生することができます。繰り返し作業の自動化やデモンストレーション作成などに役立ちます。

`keyboard.start_recording()` / `keyboard.stop_recording()` (非推奨) と `keyboard.record()`

古い情報源では start_recording()stop_recording() が紹介されていることがありますが、現在の推奨される方法は keyboard.record() を使うことです。これは指定されたキー(デフォルトは ‘esc’)が押されるまでキーボードイベントを記録し、そのリストを返します。

import keyboard
import time

print("キーボード操作の記録を開始します。何かキー入力を行ってください。")
print("'esc' キーを押すと記録を終了します。")

# 'esc' が押されるまでキーボードイベントを記録する
# suppress=True にすると、記録中のキー入力を他のアプリケーションに渡さない(キー操作をブロックする)
# trigger_on_release=True にすると、'esc'を離した時に記録を終了する
recorded_events = keyboard.record(until='esc')

print("\n記録が終了しました。")
print(f"記録されたイベント数: {len(recorded_events)}")

# 記録されたイベントを表示(オプション)
# print("記録されたイベント:")
# for event in recorded_events:
#     print(f"- {event.event_type} {event.name}")

print("\n5秒後に記録された操作を再生します...")
time.sleep(5)

# 記録されたイベントを再生する
# speed_factor で再生速度を調整(1.0が元の速度、2.0は2倍速)
# send_event 引数を False にすると、イベント送信の代わりに print する(デバッグ用)
keyboard.play(recorded_events, speed_factor=1.0)

print("\n再生が完了しました。")

record() はブロッキング関数であり、指定したキーが押されるまでプログラムの実行を停止します。記録されるのは KeyboardEvent オブジェクトのリストです。

2. キー名の取得と扱い

キーボードイベントやホットキーに関連するキー名をプログラムで扱いたい場合があります。

`keyboard.get_hotkey_name()`

複数のキー名からなるリストやタプルを、人間が読みやすいホットキーの文字列表現(例: "ctrl+shift+a")に変換します。

import keyboard

keys1 = ['ctrl', 'shift', 'a']
hotkey_name1 = keyboard.get_hotkey_name(keys1)
print(f"{keys1} -> '{hotkey_name1}'")

keys2 = ('alt', 'tab')
hotkey_name2 = keyboard.get_hotkey_name(keys2)
print(f"{keys2} -> '{hotkey_name2}'")

# 単一キーも可能
keys3 = ['esc']
hotkey_name3 = keyboard.get_hotkey_name(keys3)
print(f"{keys3} -> '{hotkey_name3}'")

`keyboard.parse_hotkey()`

ホットキーの文字列表現(例: "ctrl+alt+delete")を、個々のキー名(正規化された名前)のリストのリストにパース(解析)します。カンマ区切りで複数のステップを持つホットキーも解析できます。

import keyboard

hotkey_str1 = "ctrl+shift+esc"
parsed_hotkey1 = keyboard.parse_hotkey(hotkey_str1)
print(f"'{hotkey_str1}' -> {parsed_hotkey1}") # [['control', 'shift', 'escape']]

hotkey_str2 = "alt+f, e" # Alt+F を押した後、E を押す
parsed_hotkey2 = keyboard.parse_hotkey(hotkey_str2)
print(f"'{hotkey_str2}' -> {parsed_hotkey2}") # [['alt', 'f'], ['e']]

hotkey_str3 = "page up, page down"
parsed_hotkey3 = keyboard.parse_hotkey(hotkey_str3)
print(f"'{hotkey_str3}' -> {parsed_hotkey3}") # [['page up'], ['page down']]

この関数は、ユーザーが入力したホットキー文字列を内部的に処理する際に便利です。

3. 修飾キー (Modifier Keys) の扱い

Shift, Ctrl, Alt, Win/Cmd といった修飾キーは、他のキーと組み合わせて使われることが多いです。 keyboard ライブラリではこれらを自然に扱えます。

  • 送信時: send()press_and_release()'+' を使って組み合わせを指定します (例: 'ctrl+c')。
  • フック/ホットキー時: イベントオブジェクトの modifiers 属性で押されている修飾キーを確認したり、ホットキー登録時に '+' で組み合わせを指定したりします。
  • 左右の区別: 'left shift', 'right ctrl', 'left windows' のように左右を区別するキー名も利用可能です。

4. 特定キーのブロック

特定のキー入力をシステム全体で無効化(ブロック)することができます。⚠️ この機能は現在 Windows でのみ利用可能です。

`keyboard.block_key()` / `keyboard.unblock_key()`

import keyboard
import time
import sys

# Windows 以外では ModuleNotFoundError が発生する可能性があるため try-except
try:
    # 'a' キーと Windows キーをブロック
    keyboard.block_key('a')
    keyboard.block_key('windows') # 'win' でも可
    print("'a' キーと Windows キーをブロックしました。5秒間有効です。")
    print("ブロック解除後、ESCで終了します。")
    time.sleep(5)

    # ブロックを解除
    keyboard.unblock_key('a')
    keyboard.unblock_key('windows')
    print("\nブロックを解除しました。")

    # すべてのキーをブロック (注意: ESC もブロックされると解除が困難になる!)
    # target_keys = [...] # ブロックしたいキーのリスト
    # for key in target_keys:
    #     keyboard.block_key(key)
    # print("特定のキー群をブロックしました。")
    # time.sleep(5)
    # keyboard.unhook_all() # unblock_key の代わりに unhook_all でも解除される

    # ESCキーで終了
    keyboard.wait('esc')

except ImportError:
    print("block_key/unblock_key は Windows でのみサポートされています。")
except Exception as e:
    print(f"エラーが発生しました: {e}")
finally:
    # 念のためすべてのフック/ブロックを解除
    try:
        keyboard.unhook_all()
    except ImportError:
        pass # Windows 以外では unhook_all もエラーになる可能性がある

print("プログラムを終了します。")
非常に危険: すべてのキーや重要なシステムキー(Ctrl+Alt+Deleteなど)をブロックすると、コンピュータの操作が不能になる可能性があります。この機能の使用には最大限の注意が必要です。安易にすべてのキーをブロックするようなコードは避けるべきです。

2023年6月時点のZennの記事では、日本語キーボードを含む多くのキー名をリストアップしてブロックする例が紹介されていました。

5. 特定のキーが押されているか確認

特定のキーが現在押されているかどうかを、イベントフックを使わずに確認できます。ポーリング(定期的な確認)で状態をチェックしたい場合に便利です。

`keyboard.is_pressed()`

import keyboard
import time

print("CtrlキーとShiftキーの状態を1秒ごとに表示します。")
print("'q' キーを押すと終了します。")

while True:
    try:
        # Ctrlキーが押されているか (左右どちらでも)
        is_ctrl_pressed = keyboard.is_pressed('ctrl')
        # Shiftキーが押されているか (左右どちらでも)
        is_shift_pressed = keyboard.is_pressed('shift')
        # 'q' キーが押されているか
        is_q_pressed = keyboard.is_pressed('q')

        print(f"\rCtrl: {'押されている' if is_ctrl_pressed else '離されている'}, Shift: {'押されている' if is_shift_pressed else '離されている'}", end="")

        if is_q_pressed:
            print("\n'q' キーが押されたので終了します。")
            break

        time.sleep(0.1) # CPU負荷を下げるために少し待機

    except KeyboardInterrupt:
        print("\nCtrl+C により終了します。")
        break

print("プログラム終了。")

is_pressed() は、指定したキーが現在押されていれば True、そうでなければ False を返します。'ctrl''shift' のように左右を区別しない名前を指定すると、どちらか片方でも押されていれば True になります。'left ctrl' のように指定すれば左側のみを判定します。

これまでに学んだ機能を組み合わせて、いくつかの実用的な例を見てみましょう。

例1: 特定キーでプログラムを安全に終了

バックグラウンドで動作するスクリプトなどを、特定のホットキーで安全に停止させたい場合です。

import keyboard
import time
import threading
import sys

# プログラムが動作中であることを示すフラグ
running = True
# バックグラウンド処理を行うスレッド
background_thread = None

def background_task():
    """バックグラウンドで何か処理を行う関数(例)"""
    count = 0
    while running:
        print(f"バックグラウンド処理実行中... ({count})")
        count += 1
        time.sleep(2)
    print("バックグラウンド処理が停止しました。")

def shutdown_hook():
    """終了用ホットキーが押されたときに呼ばれる関数"""
    global running
    print("\n終了シグナル (Ctrl+Alt+End) を受信しました。")
    running = False # フラグを False にしてループを止める
    # 必要であれば、さらにクリーンアップ処理を行う
    print("プログラムを終了処理中です...")
    # スレッドが終了するのを待つ (必要に応じてタイムアウトを設定)
    if background_thread and background_thread.is_alive():
        background_thread.join(timeout=5)
    print("クリーンアップ完了。")
    keyboard.unhook_all() # フックを解除
    # sys.exit() # スレッドから直接 sys.exit() を呼ぶのは推奨されない場合がある
    #             # 代わりにメインスレッド側で終了を検知するか、
    #             # keyboard.release('esc') などで wait を解除する方が良い場合も。
    # ここでは wait を抜けるために適当なキーをリリースしてみる
    try:
        # 存在しないかもしれないが、wait を抜けるトリガーとして
        keyboard.press_and_release('esc')
    except Exception:
        pass # エラーは無視


# Ctrl + Alt + End で終了するホットキーを登録
keyboard.add_hotkey('ctrl+alt+end', shutdown_hook, trigger_on_release=True)

print("バックグラウンド処理を開始します。")
print("Ctrl + Alt + End を押すと安全に終了します。")

# バックグラウンド処理を別スレッドで開始
running = True
background_thread = threading.Thread(target=background_task, daemon=True)
background_thread.start()

# メインスレッドは終了シグナルを待つ
# shutdown_hook で 'esc' を送っているので、'esc' を待つ
try:
    keyboard.wait('esc') # shutdown_hook で解除されるのを待つ
except Exception:
     # wait 中に予期せぬエラーが起きる可能性も考慮
     pass
finally:
    # 念のため、まだ running なら停止処理
    if running:
        print("\nメインスレッドで終了処理を実行します。")
        running = False
        if background_thread and background_thread.is_alive():
            background_thread.join(timeout=5)
        keyboard.unhook_all()

print("プログラムが完全に終了しました。")

例2: 定型文の高速入力

メールの署名、よく使うコードスニペット、住所などをホットキー一発で入力できるようにします。

import keyboard
import time

def insert_signature():
    print("署名挿入ホットキー (Ctrl+Alt+S) が押されました。")
    signature = """
-----------------------------
山田 太郎 (Taro Yamada)
株式会社サンプル / Sample Inc.
部署名 / Department
Email: taro.yamada@example.com
TEL: 03-1234-5678
-----------------------------
"""
    # 少し待ってから入力開始(フォーカス移動などのため)
    time.sleep(0.2)
    keyboard.write(signature, delay=0.01)

def insert_address():
    print("住所挿入ホットキー (Ctrl+Alt+A) が押されました。")
    address = "〒100-0000 東京都千代田区千代田1-1"
    time.sleep(0.2)
    keyboard.write(address)


# ホットキーを登録
keyboard.add_hotkey('ctrl+alt+s', insert_signature)
keyboard.add_hotkey('ctrl+alt+a', insert_address)

print("定型文入力ホットキーを登録しました。")
print("- Ctrl+Alt+S: 署名を挿入")
print("- Ctrl+Alt+A: 住所を挿入")
print("ESCキーで終了します。")

keyboard.wait('esc')
keyboard.unhook_all()
print("プログラムを終了しました。")

例3: ゲーム操作の補助 (自己責任で!)

特定のキー連打や複雑なコマンド入力を簡略化するマクロを作成できます。 ⚠️ **注意:** オンラインゲームなどでこのようなマクロを使用することは、利用規約違反となり、アカウント停止(BAN)のリスクがあります。使用は自己責任で行い、規約を遵守してください。オフラインゲームや個人的な利用に留めることを強く推奨します。

import keyboard
import time
import threading

# 連打処理を実行中かどうかのフラグ
is_rapid_firing = False
rapid_fire_thread = None

def rapid_fire_action():
    """'x' キーを連打する関数"""
    while is_rapid_firing:
        keyboard.press_and_release('x')
        time.sleep(0.05) # 連打間隔 (秒)

def toggle_rapid_fire():
    """連打の開始/停止を切り替える関数"""
    global is_rapid_firing, rapid_fire_thread
    if is_rapid_firing:
        print("連打停止 (F1)")
        is_rapid_firing = False
        if rapid_fire_thread and rapid_fire_thread.is_alive():
            rapid_fire_thread.join() # スレッドの終了を待つ
        rapid_fire_thread = None
    else:
        print("連打開始 (F1)")
        is_rapid_firing = True
        # 連打処理を別スレッドで開始
        rapid_fire_thread = threading.Thread(target=rapid_fire_action, daemon=True)
        rapid_fire_thread.start()

# F1キーで連打のON/OFFを切り替え
keyboard.add_hotkey('f1', toggle_rapid_fire, trigger_on_release=True)

print("ゲーム補助スクリプト(連打機能)を開始しました。")
print("- F1キーで 'x' キーの連打を開始/停止します。")
print("注意: オンラインゲームでの使用は規約違反の可能性があります。")
print("ESCキーでプログラムを終了します。")

keyboard.wait('esc')

# 終了時に連打スレッドが動いていれば停止させる
if is_rapid_firing:
    is_rapid_firing = False
    if rapid_fire_thread and rapid_fire_thread.is_alive():
        rapid_fire_thread.join()

keyboard.unhook_all()
print("プログラムを終了しました。")

例4: カスタムショートカットキー

OSやアプリケーションが提供していない、自分だけの便利なショートカットキーを作成します。例えば、特定のフォルダを開く、特定のアプリケーションを起動するなど。

import keyboard
import os
import subprocess
import sys

def open_documents_folder():
    print("ドキュメントフォルダを開くホットキー (Win+Alt+D) が押されました。")
    try:
        if sys.platform == 'win32':
            # Windows の場合: エクスプローラーでドキュメントフォルダを開く
            docs_path = os.path.join(os.path.expanduser("~"), "Documents")
            os.startfile(docs_path)
        elif sys.platform == 'darwin':
            # macOS の場合: Finder で書類フォルダを開く
            docs_path = os.path.join(os.path.expanduser("~"), "Documents")
            subprocess.run(['open', docs_path])
        elif sys.platform.startswith('linux'):
            # Linux の場合 (xdg-open を使用)
            docs_path = os.path.join(os.path.expanduser("~"), "Documents")
            if not os.path.exists(docs_path):
                 docs_path = os.path.expanduser("~") # Documents がなければホームを開く
            subprocess.run(['xdg-open', docs_path])
        else:
            print(f"未対応のOSです: {sys.platform}")
    except Exception as e:
        print(f"フォルダを開けませんでした: {e}")

def launch_calculator():
    print("電卓起動ホットキー (Win+Alt+C) が押されました。")
    try:
        if sys.platform == 'win32':
            subprocess.run(['calc.exe'])
        elif sys.platform == 'darwin':
            subprocess.run(['open', '-a', 'Calculator'])
        elif sys.platform.startswith('linux'):
            # gnome-calculator や kcalc など、環境によって異なる可能性あり
            try:
                subprocess.run(['gnome-calculator'])
            except FileNotFoundError:
                try:
                    subprocess.run(['kcalc'])
                except FileNotFoundError:
                     print("電卓が見つかりませんでした。")
        else:
            print(f"未対応のOSです: {sys.platform}")
    except Exception as e:
        print(f"電卓を起動できませんでした: {e}")

# ホットキーを登録 (Winキーは 'windows' または 'win'、macOSのCmdは 'cmd')
# OS によって Win/Cmd のキー名が変わる場合があるので注意
hotkey_modifier = 'windows' if sys.platform == 'win32' else 'cmd' if sys.platform == 'darwin' else 'alt' # Linux は例として Alt

keyboard.add_hotkey(f'{hotkey_modifier}+alt+d', open_documents_folder)
keyboard.add_hotkey(f'{hotkey_modifier}+alt+c', launch_calculator)


print("カスタムショートカットキーを登録しました。")
print(f"- {hotkey_modifier}+Alt+D: ドキュメントフォルダを開く")
print(f"- {hotkey_modifier}+Alt+C: 電卓を起動")
print("ESCキーで終了します。")

keyboard.wait('esc')
keyboard.unhook_all()
print("プログラムを終了しました。")

注意点とトラブルシューティング ⚠️

keyboard ライブラリは非常に便利ですが、利用する上でいくつか注意すべき点や、遭遇する可能性のある問題があります。

1. 管理者/root権限の必要性

前述の通り、このライブラリはシステム全体のキーボードイベントを監視・操作するため、多くの場合、管理者権限(Windows)またはroot権限(Linux)が必要です。macOSでも同様に特別な許可設定と sudo が必要になることがあります。

  • 理由: 低レベルのキーボードアクセスは、悪意のあるプログラム(キーロガーなど)に利用される可能性があるため、OSのセキュリティ機構によって保護されています。権限がないと、OSがキーボードイベントへのアクセスを許可しません。
  • 対処法:
    • Windows: コマンドプロンプトやIDEを「管理者として実行」する。
    • Linux: sudo python your_script.py のように sudo を付けて実行する。
    • macOS: ターミナルやIDEに「アクセシビリティ」の許可を与え、必要に応じて sudo を付けて実行する。
  • 代替案: どうしても管理者権限を使いたくない、または使えない場合は、pynput ライブラリを検討してください。pynputkeyboard と同様の機能を提供し、多くの場合、管理者権限なしでも(一部機能制限があるかもしれませんが)動作します。

2. macOSでのアクセシビリティ設定

macOSで keyboard ライブラリ(または pynput も同様)を使用するには、スクリプトを実行するアプリケーション(例: ターミナル, VSCode, PyCharm, IDLEなど)にアクセシビリティ機能へのアクセスを許可する必要があります。

  1. 「システム環境設定」(または「システム設定」)を開きます。
  2. 「セキュリティとプライバシー」(または「プライバシーとセキュリティ」)を選択します。
  3. 「プライバシー」タブを選択し、左のリストから「アクセシビリティ」をクリックします。
  4. 左下の鍵アイコンをクリックして、パスワードを入力し、設定を変更可能にします。
  5. 「+」ボタンをクリックし、keyboard ライブラリを使用するアプリケーション(例: /Applications/Utilities/Terminal.app や、使用しているIDE)を追加し、チェックボックスをオンにします。
  6. 設定を有効にするために、追加したアプリケーションの再起動が必要な場合があります。

この設定を行わないと、キー入力の監視やシミュレーションが正しく動作しません。2024年3月の情報では、macOS環境での `keyboard` ライブラリはまだ使いにくい点があり、特にプログラム終了時にキャッシュされていたキー入力が一気に出力されるなどの問題が報告されています。

3. パフォーマンスへの影響

グローバルキーボードフックは、システム上で発生するすべてのキーボードイベントを捕捉して処理するため、CPUリソースを消費します。特に、コールバック関数内で重い処理を行うと、システム全体の応答性に影響を与える可能性があります。

  • 対処法:
    • コールバック関数内の処理は、できるだけ軽量かつ高速に完了するように心がける。
    • 重い処理が必要な場合は、コールバック関数内ではキューにタスクを入れるだけにし、別のスレッドで実際の処理を行うなどの工夫をする。
    • 不要になったフックは keyboard.unhook()keyboard.unhook_all() で速やかに解除する。
    • ポーリングで十分な場合は keyboard.is_pressed() の使用を検討する(ただし、これも頻繁に呼び出すとCPU負荷がかかる)。

4. セキュリティリスク 💀

keyboard ライブラリは、その性質上、キーロガー(キー入力を記録するマルウェア)を作成するためにも利用できてしまいます。

  • 注意点:
    • このライブラリを使用して作成したプログラムを配布・実行する際は、その目的と動作を明確にし、悪用されないように注意する。
    • ライブラリの作者は、キーロガーなどの不正利用について責任を負いません。倫理的な利用を心がけてください。
    • 管理者権限で実行するため、スクリプト自体のセキュリティにも十分配慮が必要です。

5. 他のプログラムとの競合

他のアプリケーション(特にゲームやセキュリティソフトなど)が、低レベルでキーボードフックを行っている場合、keyboard ライブラリがイベントを正常に捕捉できない、またはキー入力のシミュレーションが効かないことがあります。これは「キーイベントが飲み込まれる(swallowed)」と表現されます。

  • 対処法: 残念ながら、アプリケーション側が意図的にキーイベントをブロックしている場合、keyboard ライブラリ側でできることは限られます。競合するアプリケーションを特定し、設定を変更するか、使用を避けるなどの対策が必要になる場合があります。
  • ゲーム内での自動操作などは、ゲーム側が検出・ブロックする仕組みを持っていることが多いです。

6. 文字化けや意図しない動作

  • キー名の不一致: 使用しているキーボードレイアウトやOSの設定によっては、特定の記号キーなどの名前が keyboard ライブラリが想定しているものと異なる場合があります。keyboard.hook() で実際にどのような event.nameevent.scan_code が返ってくるかを確認すると良いでしょう。
  • `write()` 関数の挙動: write() 関数は内部的にキーの押下・解放をシミュレートしますが、タイミングによってはOSやアプリケーションの挙動と干渉し、文字が抜けたり、順序がおかしくなったりすることが稀にあります。delay 引数を調整したり、press_and_release() を使ってより細かく制御したりすることで改善する場合があります。
  • Linuxでのメディアキー: Linux環境では、一部のメディアキー(音量調整、再生/停止など)が名前なし(スキャンコードのみ)で報告されたり、全く報告されなかったりすることがあります。

7. ライブラリのメンテナンス状況

PyPIで公開されている keyboard ライブラリの最終更新は 0.13.5 で、2020年3月23日となっています。GitHubリポジトリ (boppreh/keyboard) ではその後も更新があるかもしれませんが、活発なメンテナンスが続いているか、将来的なPythonバージョンやOSアップデートへの追従が行われるかは注意が必要です。代替ライブラリとして pynput はより活発に開発が続けられている傾向があります。

Pythonでキーボード(およびマウス)操作を行うライブラリとして、keyboard と並んでよく挙げられるのが pynput です。どちらを選ぶべきか迷うこともあるでしょう。簡単な比較を表にまとめます。

特徴 keyboard pynput
主な機能 キーボードフック、シミュレーション、ホットキー、記録/再生、ブロック(Winのみ) キーボード/マウス フック、シミュレーション、ホットキー
依存関係 なし (Pure Python) OS固有の依存関係あり (例: LinuxではXlib関連)
インストール pip install keyboard pip install pynput
管理者/root権限 ほぼ必須 (特にLinux, macOS) 不要な場合が多い (一部機能で必要になる可能性あり)
macOS サポート 実験的 (不安定な可能性あり) 比較的安定 (アクセシビリティ設定は必要)
マウス操作 非対応 (別ライブラリ mouse が必要) 対応
APIの複雑さ 比較的シンプル ややオブジェクト指向的 (Controller, Listenerクラスなど)
メンテナンス状況 更新頻度は低め? (2020年以降停滞気味の可能性) 比較的活発
キー入力の信頼性 (高速入力時) (情報少) 高速入力時にイベント欠落や順序違いが発生する可能性が指摘されている (2023年9月情報)

どちらを選ぶか?

  • 手軽さ、依存関係なしを重視する場合: keyboard は良い選択肢ですが、権限問題とmacOSの不安定さに注意が必要です。
  • マウス操作も扱いたい、管理者権限を避けたい、macOSでの安定性を求める場合: pynput の方が適している可能性が高いです。
  • 特定の機能が必要な場合: キーブロック機能は keyboard (Windowsのみ) の特徴です。

両方のライブラリを試してみて、自分のプロジェクト要件や開発環境に合った方を選択するのが良いでしょう。

このブログ記事では、Pythonの keyboard ライブラリについて、インストールから基本的な使い方(フック、送信、ホットキー)、高度な機能(記録再生、キー名操作、ブロック、状態確認)、実用例、そして重要な注意点や pynput との比較まで、幅広く解説しました。✅

keyboard ライブラリは、そのシンプルさと機能性から、Pythonでキーボード操作を自動化したり、インタラクティブなツールを作成したりする際に非常に強力な武器となります。しかし、その強力さゆえに、管理者権限の必要性やセキュリティリスク、OSごとの挙動の違いなど、注意すべき点も少なくありません。

この記事で得た知識をもとに、ぜひ keyboard ライブラリを活用して、あなたのPythonプロジェクトをより便利で効率的なものにしてみてください。実験を恐れず、ドキュメントや他のユーザーのコードを参考にしながら、様々な可能性を探求していくことが、スキルアップへの近道です。🚀

Happy Coding! ✨