Introduction
Keyboard input automation and event handling are essential aspects both for application testing and for creating custom scripts and utilities. When you need to programmatically press keys, respond to input, or create your own hotkeys, Python offers an excellent library – keyboard.
keyboard is a powerful cross‑platform tool that allows you to control the keyboard at the operating‑system level. It works as both a listener and an event generator: you can intercept and emulate keyboard input.
In this article we will explore the keyboard library in detail, from installation to advanced scenarios, including macro creation, global hotkeys, loggers, and combo‑command handling.
Installation and Requirements
Install the library via pip:
pip install keyboard
System Requirements
Windows: The library works out of the box without additional configuration.
Linux: Requires root access to capture global keyboard events. For local use you can run with sudo.
macOS: Partially limited and requires additional permissions in the security settings. You must grant access to Accessibility features.
Main Features of the Library
The keyboard library provides a wide range of functions for working with the keyboard:
Key Press Emulation
The library allows you to programmatically mimic key presses, which is useful for automating repetitive tasks.
Keyboard Event Interception
The ability to monitor key presses in real time, creating your own event handlers.
Hotkey Creation
Register global key combinations for quick access to functions.
Macro Recording and Playback
Functionality for recording a sequence of key presses and replaying them later.
Basic Key Emulation Functions
Typing Text
import keyboard
# Simple text typing
keyboard.write("Hello, world!")
# Typing with a delay between characters
keyboard.write("Slow typing", delay=0.1)
Pressing and Releasing Keys
# Press a key (hold)
keyboard.press("ctrl")
# Release a key
keyboard.release("ctrl")
# Press and immediately release
keyboard.press_and_release("enter")
Key Combinations
# Send a combination
keyboard.send("ctrl+c")
keyboard.send("ctrl+shift+n")
# Alternative method
keyboard.press("ctrl")
keyboard.press("c")
keyboard.release("c")
keyboard.release("ctrl")
Working with Hotkeys
Registering Hotkeys
import keyboard
def launch_notepad():
print("Launching Notepad!")
# Add code here to start an application
# Register a hotkey
keyboard.add_hotkey("ctrl+alt+n", launch_notepad)
# Wait for Esc to exit
keyboard.wait("esc")
Multiple Combinations
# Combination of several sequential presses
keyboard.add_hotkey("ctrl+alt+a, ctrl+alt+b", lambda: print("Complex combo!"))
Managing Hotkeys
# Remove a specific hotkey
hotkey = keyboard.add_hotkey("ctrl+space", lambda: print("Hotkey!"))
keyboard.remove_hotkey(hotkey)
# Clear all hotkeys
keyboard.clear_hotkeys()
Keyboard Event Handling
Tracking Presses
def on_key_press(event):
print(f"Key pressed: {event.name}")
def on_key_release(event):
print(f"Key released: {event.name}")
# Register handlers
keyboard.on_press(on_key_press)
keyboard.on_release(on_key_release)
# Wait for termination
keyboard.wait("esc")
Checking Key States
import time
while True:
if keyboard.is_pressed("space"):
print("Spacebar is pressed!")
if keyboard.is_pressed("ctrl+shift"):
print("Ctrl+Shift are pressed together!")
break
time.sleep(0.1)
Reading Events
# Read a single event
event = keyboard.read_event()
print(f"Event: {event.name}, type: {event.event_type}")
# Read a pressed key
key = keyboard.read_key()
print(f"Key pressed: {key}")
# Read a hotkey
hotkey = keyboard.read_hotkey()
print(f"Combination pressed: {hotkey}")
Macro Recording and Playback
Recording a Macro
print("Starting macro recording. Press Esc to finish.")
events = keyboard.record(until="esc")
print(f"Recorded {len(events)} events")
Playing Back a Macro
# Playback at normal speed
keyboard.play(events)
# Playback at double speed
keyboard.play(events, speed_factor=2.0)
# Playback at half speed
keyboard.play(events, speed_factor=0.5)
Saving and Loading Macros
import json
# Save macro to a file
def save_macro(events, filename):
with open(filename, 'w') as f:
json.dump([(e.name, e.event_type, e.time) for e in events], f)
# Load macro from a file
def load_macro(filename):
with open(filename, 'r') as f:
data = json.load(f)
return [keyboard.KeyboardEvent(name, event_type, time)
for name, event_type, time in data]
# Usage
events = keyboard.record(until="esc")
save_macro(events, "my_macro.json")
loaded_events = load_macro("my_macro.json")
keyboard.play(loaded_events)
Blocking and Suppressing Keys
Blocking Keys
# Block a key
keyboard.block_key("a")
print("Key 'a' blocked")
# Unblock a key
keyboard.unblock_key("a")
print("Key 'a' unblocked")
Suppressing Keys
# Suppress the Win key action
keyboard.suppress_key("win")
print("Win key suppressed")
Complete Method and Function Reference
| Method / Function | Description | Usage Example |
|---|---|---|
keyboard.write(text) |
Type text | keyboard.write("Hello") |
keyboard.press(key) |
Press a key | keyboard.press("ctrl") |
keyboard.release(key) |
Release a key | keyboard.release("ctrl") |
keyboard.press_and_release(key) |
Press and release | keyboard.press_and_release("enter") |
keyboard.send(key) |
Send a key / combination | keyboard.send("ctrl+c") |
keyboard.add_hotkey(hotkey, callback) |
Register a hotkey | keyboard.add_hotkey("ctrl+alt+h", func) |
keyboard.remove_hotkey(hotkey) |
Remove a hotkey | keyboard.remove_hotkey(hotkey) |
keyboard.clear_hotkeys() |
Clear all hotkeys | keyboard.clear_hotkeys() |
keyboard.wait(key) |
Wait for a key press | keyboard.wait("esc") |
keyboard.read_key() |
Read a pressed key | key = keyboard.read_key() |
keyboard.read_event() |
Read a keyboard event | event = keyboard.read_event() |
keyboard.read_hotkey() |
Read a hotkey | hotkey = keyboard.read_hotkey() |
keyboard.record(until) |
Record events | events = keyboard.record(until="esc") |
keyboard.play(events) |
Play back events | keyboard.play(events) |
keyboard.is_pressed(key) |
Check if a key is pressed | if keyboard.is_pressed("space"): |
keyboard.on_press(callback) |
Press handler | keyboard.on_press(func) |
keyboard.on_release(callback) |
Release handler | keyboard.on_release(func) |
keyboard.hook(callback) |
Global handler | keyboard.hook(func) |
keyboard.unhook_all() |
Remove all hooks | keyboard.unhook_all() |
keyboard.block_key(key) |
Block a key | keyboard.block_key("a") |
keyboard.unblock_key(key) |
Unblock a key | keyboard.unblock_key("a") |
keyboard.suppress_key(key) |
Suppress a key | keyboard.suppress_key("win") |
keyboard.get_hotkey_name() |
Get hotkey name | name = keyboard.get_hotkey_name() |
Practical Usage Examples
Automating Routine Tasks
import keyboard
import time
def auto_responder():
"""Automatic chat responder"""
while True:
if keyboard.is_pressed("f1"):
keyboard.write("Hello! How are you?")
keyboard.press_and_release("enter")
time.sleep(0.5)
elif keyboard.is_pressed("f2"):
keyboard.write("Thank you for reaching out!")
keyboard.press_and_release("enter")
time.sleep(0.5)
elif keyboard.is_pressed("esc"):
break
time.sleep(0.1)
# Start the auto‑responder
auto_responder()
Creating Custom Hotkeys
import keyboard
import subprocess
import webbrowser
def open_calculator():
"""Open Calculator"""
subprocess.run("calc.exe")
def open_notepad():
"""Open Notepad"""
subprocess.run("notepad.exe")
def open_browser():
"""Open Browser"""
webbrowser.open("https://www.google.com")
# Register hotkeys
keyboard.add_hotkey("ctrl+alt+c", open_calculator)
keyboard.add_hotkey("ctrl+alt+n", open_notepad)
keyboard.add_hotkey("ctrl+alt+b", open_browser)
print("Hotkeys activated:")
print("Ctrl+Alt+C – Calculator")
print("Ctrl+Alt+N – Notepad")
print("Ctrl+Alt+B – Browser")
print("Press Esc to exit")
keyboard.wait("esc")
Key Press Logger
import keyboard
import datetime
def key_logger():
"""Simple key press logger"""
log_file = "keylog.txt"
def log_key(event):
if event.event_type == keyboard.KEY_DOWN:
timestamp = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
with open(log_file, "a", encoding="utf-8") as f:
f.write(f"{timestamp} - {event.name}\n")
keyboard.hook(log_key)
print("Logger started. Press Esc to stop.")
keyboard.wait("esc")
# Run the logger
key_logger()
Security and Best Practices
Exception Handling
import keyboard
def safe_hotkey_handler():
try:
keyboard.add_hotkey("ctrl+alt+q", lambda: print("Safe hotkey"))
keyboard.wait("esc")
except KeyboardInterrupt:
print("Program interrupted by user")
except Exception as e:
print(f"Error: {e}")
finally:
keyboard.clear_hotkeys()
print("Hotkeys cleared")
safe_hotkey_handler()
Avoiding Conflicts
import keyboard
def prevent_conflicts():
"""Avoid conflicts with system hotkeys"""
# List of system combos that should not be intercepted
system_hotkeys = [
"ctrl+alt+del",
"alt+f4",
"win+l",
"ctrl+shift+esc"
]
def safe_add_hotkey(hotkey, callback):
if hotkey.lower() in system_hotkeys:
print(f"Warning: {hotkey} is a system shortcut")
return None
return keyboard.add_hotkey(hotkey, callback)
# Safe registration
safe_add_hotkey("ctrl+alt+h", lambda: print("Safe combo"))
prevent_conflicts()
Integration with Other Libraries
Using Together with PyAutoGUI
import keyboard
import pyautogui
def screenshot_on_hotkey():
"""Take a screenshot via hotkey"""
def take_screenshot():
screenshot = pyautogui.screenshot()
screenshot.save("screenshot.png")
print("Screenshot saved!")
keyboard.add_hotkey("ctrl+shift+s", take_screenshot)
keyboard.wait("esc")
screenshot_on_hotkey()
Integration with GUI Frameworks
import keyboard
import tkinter as tk
from tkinter import messagebox
def gui_with_hotkeys():
"""GUI app with hotkeys"""
root = tk.Tk()
root.title("Hotkey‑Enabled Application")
def show_message():
messagebox.showinfo("Message", "Hotkey triggered!")
# Register hotkey
keyboard.add_hotkey("ctrl+space", show_message)
label = tk.Label(root, text="Press Ctrl+Space to show a message")
label.pack(pady=20)
root.mainloop()
gui_with_hotkeys()
Debugging and Diagnostics
Event Debugging
import keyboard
def debug_events():
"""Debug keyboard events"""
def debug_callback(event):
print(f"Event: {event.name}")
print(f"Type: {event.event_type}")
print(f"Time: {event.time}")
print(f"Scan code: {event.scan_code}")
print("-" * 30)
keyboard.hook(debug_callback)
keyboard.wait("esc")
debug_events()
Testing Hotkeys
import keyboard
def test_hotkeys():
"""Test hotkey functionality"""
test_combinations = [
("ctrl+a", "Select All"),
("ctrl+c", "Copy"),
("ctrl+v", "Paste"),
("ctrl+z", "Undo")
]
for combo, description in test_combinations:
keyboard.add_hotkey(combo, lambda desc=description: print(f"Triggered: {desc}"))
print("Hotkey testing started")
keyboard.wait("esc")
test_hotkeys()
Frequently Asked Questions
Why doesn't the library work in my environment?
The keyboard library requires direct access to system keyboard events. In some environments (virtual machines, remote desktops, sandboxes) this access may be restricted.
How to fix permission issues on Linux?
On Linux you need to run as root or add the user to the input group. You can also create udev rules to grant access to input devices.
Can the library be used for games?
Yes, but many anti‑cheat systems can detect programmatic key emulation. For games it’s recommended to use official APIs or specialized solutions.
How to handle national keyboard layouts?
The library works with physical keys, so the layout influences the result. For correct text handling use keyboard.write() instead of raw key emulation.
Why do hotkeys not work in certain applications?
Some applications capture keyboard events at a low level. In such cases you may need alternative methods or libraries.
Limitations and Specifics
Platform Limitations
Windows: Full support for all features. May encounter issues with UAC dialogs.
Linux: Requires root for global hooks. May conflict with X11/Wayland.
macOS: Requires Accessibility permissions. Some functions have limited support.
Technical Limitations
The library does not work in browser environments or certain virtual containers. In RDP sessions it may behave unpredictably. Some antivirus programs can block key‑emulation functions.
Comparison with Alternative Solutions
| Library | Language | Key Capture | Hotkeys | Macro Recording | Cross‑Platform |
|---|---|---|---|---|---|
| keyboard | Python | Yes | Yes | Yes | Partial |
| pynput | Python | Yes | Partial | No | Yes |
| AutoHotkey | Own | Yes | Yes | Yes | Windows only |
| pyautogui | Python | No | No | No | Yes |
| pykeyboard | Python | Yes | No | No | Yes |
Performance Optimization
Efficient Hook Usage
import keyboard
def optimized_hook():
"""Optimized event hook"""
def efficient_callback(event):
# Filter only needed events
if event.event_type == keyboard.KEY_DOWN:
if event.name in ['a', 'b', 'c']:
# Process only required keys
process_key(event.name)
keyboard.hook(efficient_callback)
keyboard.wait("esc")
def process_key(key):
print(f"Processed key: {key}")
optimized_hook()
Resource Management
import keyboard
import atexit
def resource_management():
"""Manage library resources"""
def cleanup():
keyboard.unhook_all()
keyboard.clear_hotkeys()
print("Resources cleaned up")
# Register cleanup function
atexit.register(cleanup)
# Main program logic
keyboard.add_hotkey("ctrl+q", lambda: print("Exit"))
keyboard.wait("esc")
resource_management()
Conclusion
The keyboard library is a powerful and versatile tool for working with the keyboard in Python. It offers a rich set of functions for emulating presses, intercepting events, creating hotkeys, and recording macros.
Key advantages include ease of use, extensive functionality, the ability to build complex automation solutions, and an active developer community.
When using the library, it is important to consider platform constraints, handle exceptions properly, and follow security best practices. Proper use of keyboard can greatly simplify task automation and the creation of custom utilities.
The Future of AI in Mathematics and Everyday Life: How Intelligent Agents Are Already Changing the Game
Experts warned about the risks of fake charity with AI
In Russia, universal AI-agent for robots and industrial processes was developed