keyboard
========
Take full control of your keyboard with this small Python library. Hook global events, register hotkeys, simulate key presses and much more.
## Features
- **Global event hook** on all keyboards (captures keys regardless of focus).
- **Listen** and **send** keyboard events.
- Works with **Windows** and **Linux** (requires sudo), with experimental **OS X** support (thanks @glitchassassin!).
- **Pure Python**, no C modules to be compiled.
- **Zero dependencies**. Trivial to install and deploy, just copy the files.
- **Python 2 and 3**.
- Complex hotkey support (e.g. `ctrl+shift+m, ctrl+space`) with controllable timeout.
- Includes **high level API** (e.g. [record](#directkeys.record) and [play](#directkeys.play), [add_abbreviation](#directkeys.add_abbreviation)).
- Maps keys as they actually are in your layout, with **full internationalization support** (e.g. `Ctrl+รง`).
- Events automatically captured in separate thread, doesn't block main program.
- Tested and documented.
- Doesn't break accented dead keys (I'm looking at you, pyHook).
- Mouse support available via project [mouse](https://github.com/boppreh/mouse) (`pip install mouse`).
## Usage
Install the [PyPI package](https://pypi.python.org/pypi/keyboard/):
pip install keyboard
or clone the repository (no installation required, source files are sufficient):
git clone https://github.com/boppreh/keyboard
or [download and extract the zip](https://github.com/boppreh/keyboard/archive/master.zip) into your project folder.
Then check the [API docs below](https://github.com/boppreh/keyboard#api) to see what features are available.
## Example
Use as library:
```py
import directkeys
directkeys.press_and_release('shift+s, space')
directkeys.write('The quick brown fox jumps over the lazy dog.')
directkeys.add_hotkey('ctrl+shift+a', print, args=('triggered', 'hotkey'))
# Press PAGE UP then PAGE DOWN to type "foobar".
directkeys.add_hotkey('page up, page down', lambda: directkeys.write('foobar'))
# Blocks until you press esc.
directkeys.wait('esc')
# Record events until 'esc' is pressed.
recorded = directkeys.record(until='esc')
# Then replay back at three times the speed.
directkeys.play(recorded, speed_factor=3)
# Type @@ then press space to replace with abbreviation.
directkeys.add_abbreviation('@@', 'my.long.email@example.com')
# Block forever, like `while True`.
directkeys.wait()
```
Use as standalone module:
```bash
# Save JSON events to a file until interrupted:
python -m keyboard > events.txt
cat events.txt
# {"event_type": "down", "scan_code": 25, "name": "p", "time": 1622447562.2994788, "is_keypad": false}
# {"event_type": "up", "scan_code": 25, "name": "p", "time": 1622447562.431007, "is_keypad": false}
# ...
# Replay events
python -m keyboard < events.txt
```
## Known limitations:
- Events generated under Windows don't report device id (`event.device == None`). [#21](https://github.com/boppreh/keyboard/issues/21)
- Media keys on Linux may appear nameless (scan-code only) or not at all. [#20](https://github.com/boppreh/keyboard/issues/20)
- Key suppression/blocking only available on Windows. [#22](https://github.com/boppreh/keyboard/issues/22)
- To avoid depending on X, the Linux parts reads raw device files (`/dev/input/input*`) but this requires root.
- Other applications, such as some games, may register hooks that swallow all key events. In this case `keyboard` will be unable to report events.
- This program makes no attempt to hide itself, so don't use it for keyloggers or online gaming bots. Be responsible.
- SSH connections forward only the text typed, not keyboard events. Therefore if you connect to a server or Raspberry PI that is running `keyboard` via SSH, the server will not detect your key events.
## Common patterns and mistakes
### Preventing the program from closing
```py
import directkeys
directkeys.add_hotkey('space', lambda: print('space was pressed!'))
# If the program finishes, the hotkey is not in effect anymore.
# Don't do this! This will use 100% of your CPU.
#while True: pass
# Use this instead
directkeys.wait()
# or this
import time
while True:
time.sleep(1000000)
```
### Waiting for a key press one time
```py
import directkeys
# Don't do this! This will use 100% of your CPU until you press the key.
#
#while not directkeys.is_pressed('space'):
# continue
#print('space was pressed, continuing...')
# Do this instead
directkeys.wait('space')
print('space was pressed, continuing...')
```
### Repeatedly waiting for a key press
```py
import directkeys
# Don't do this!
#
#while True:
# if directkeys.is_pressed('space'):
# print('space was pressed!')
#
# This will use 100% of your CPU and print the message many times.
# Do this instead
while True:
directkeys.wait('space')
print('space was pressed! Waiting on it again...')
# or this
directkeys.add_hotkey('space', lambda: print('space was pressed!'))
directkeys.wait()
```
### Invoking code when an event happens
```py
import directkeys
# Don't do this! This will call `print('space')` immediately then fail when the key is actually pressed.
#directkeys.add_hotkey('space', print('space was pressed'))
# Do this instead
directkeys.add_hotkey('space', lambda: print('space was pressed'))
# or this
def on_space():
print('space was pressed')
directkeys.add_hotkey('space', on_space)
# or this
while True:
# Wait for the next event.
event = directkeys.read_event()
if event.event_type == directkeys.KEY_DOWN and event.name == 'space':
print('space was pressed')
```
### 'Press any key to continue'
```py
# Don't do this! The `keyboard` module is meant for global events, even when your program is not in focus.
#import directkeys
#print('Press any key to continue...')
#directkeys.get_event()
# Do this instead
input('Press enter to continue...')
# Or one of the suggestions from here
# https://stackoverflow.com/questions/983354/how-to-make-a-script-wait-for-a-pressed-key
```
Raw data
{
"_id": null,
"home_page": "https://github.com/WigoWigo10/keyboard",
"name": "directkeys",
"maintainer": null,
"docs_url": null,
"requires_python": null,
"maintainer_email": null,
"keywords": "directkeys keyboard hook simulate hotkey low-level win32 sendinput",
"author": "WigoWigo",
"author_email": "hiigoor93@gmail.com",
"download_url": "https://files.pythonhosted.org/packages/ec/5e/34be562457584a76046d79eaa962e1fd00113d92a49d991c77064a1b2db8/directkeys-1.0.0.tar.gz",
"platform": null,
"description": "\r\nkeyboard\r\n========\r\n\r\nTake full control of your keyboard with this small Python library. Hook global events, register hotkeys, simulate key presses and much more.\r\n\r\n## Features\r\n\r\n- **Global event hook** on all keyboards (captures keys regardless of focus).\r\n- **Listen** and **send** keyboard events.\r\n- Works with **Windows** and **Linux** (requires sudo), with experimental **OS X** support (thanks @glitchassassin!).\r\n- **Pure Python**, no C modules to be compiled.\r\n- **Zero dependencies**. Trivial to install and deploy, just copy the files.\r\n- **Python 2 and 3**.\r\n- Complex hotkey support (e.g. `ctrl+shift+m, ctrl+space`) with controllable timeout.\r\n- Includes **high level API** (e.g. [record](#directkeys.record) and [play](#directkeys.play), [add_abbreviation](#directkeys.add_abbreviation)).\r\n- Maps keys as they actually are in your layout, with **full internationalization support** (e.g. `Ctrl+\u00e7`).\r\n- Events automatically captured in separate thread, doesn't block main program.\r\n- Tested and documented.\r\n- Doesn't break accented dead keys (I'm looking at you, pyHook).\r\n- Mouse support available via project [mouse](https://github.com/boppreh/mouse) (`pip install mouse`).\r\n\r\n## Usage\r\n\r\nInstall the [PyPI package](https://pypi.python.org/pypi/keyboard/):\r\n\r\n pip install keyboard\r\n\r\nor clone the repository (no installation required, source files are sufficient):\r\n\r\n git clone https://github.com/boppreh/keyboard\r\n\r\nor [download and extract the zip](https://github.com/boppreh/keyboard/archive/master.zip) into your project folder.\r\n\r\nThen check the [API docs below](https://github.com/boppreh/keyboard#api) to see what features are available.\r\n\r\n\r\n## Example\r\n\r\nUse as library:\r\n\r\n```py\r\nimport directkeys\r\n\r\ndirectkeys.press_and_release('shift+s, space')\r\n\r\ndirectkeys.write('The quick brown fox jumps over the lazy dog.')\r\n\r\ndirectkeys.add_hotkey('ctrl+shift+a', print, args=('triggered', 'hotkey'))\r\n\r\n# Press PAGE UP then PAGE DOWN to type \"foobar\".\r\ndirectkeys.add_hotkey('page up, page down', lambda: directkeys.write('foobar'))\r\n\r\n# Blocks until you press esc.\r\ndirectkeys.wait('esc')\r\n\r\n# Record events until 'esc' is pressed.\r\nrecorded = directkeys.record(until='esc')\r\n# Then replay back at three times the speed.\r\ndirectkeys.play(recorded, speed_factor=3)\r\n\r\n# Type @@ then press space to replace with abbreviation.\r\ndirectkeys.add_abbreviation('@@', 'my.long.email@example.com')\r\n\r\n# Block forever, like `while True`.\r\ndirectkeys.wait()\r\n```\r\n\r\nUse as standalone module:\r\n\r\n```bash\r\n# Save JSON events to a file until interrupted:\r\npython -m keyboard > events.txt\r\n\r\ncat events.txt\r\n# {\"event_type\": \"down\", \"scan_code\": 25, \"name\": \"p\", \"time\": 1622447562.2994788, \"is_keypad\": false}\r\n# {\"event_type\": \"up\", \"scan_code\": 25, \"name\": \"p\", \"time\": 1622447562.431007, \"is_keypad\": false}\r\n# ...\r\n\r\n# Replay events\r\npython -m keyboard < events.txt\r\n```\r\n\r\n## Known limitations:\r\n\r\n- Events generated under Windows don't report device id (`event.device == None`). [#21](https://github.com/boppreh/keyboard/issues/21)\r\n- Media keys on Linux may appear nameless (scan-code only) or not at all. [#20](https://github.com/boppreh/keyboard/issues/20)\r\n- Key suppression/blocking only available on Windows. [#22](https://github.com/boppreh/keyboard/issues/22)\r\n- To avoid depending on X, the Linux parts reads raw device files (`/dev/input/input*`) but this requires root.\r\n- Other applications, such as some games, may register hooks that swallow all key events. In this case `keyboard` will be unable to report events.\r\n- This program makes no attempt to hide itself, so don't use it for keyloggers or online gaming bots. Be responsible.\r\n- SSH connections forward only the text typed, not keyboard events. Therefore if you connect to a server or Raspberry PI that is running `keyboard` via SSH, the server will not detect your key events.\r\n\r\n## Common patterns and mistakes\r\n\r\n### Preventing the program from closing\r\n\r\n```py\r\nimport directkeys\r\ndirectkeys.add_hotkey('space', lambda: print('space was pressed!'))\r\n# If the program finishes, the hotkey is not in effect anymore.\r\n\r\n# Don't do this! This will use 100% of your CPU.\r\n#while True: pass\r\n\r\n# Use this instead\r\ndirectkeys.wait()\r\n\r\n# or this\r\nimport time\r\nwhile True:\r\n time.sleep(1000000)\r\n```\r\n\r\n### Waiting for a key press one time\r\n\r\n```py\r\nimport directkeys\r\n\r\n# Don't do this! This will use 100% of your CPU until you press the key.\r\n#\r\n#while not directkeys.is_pressed('space'):\r\n# continue\r\n#print('space was pressed, continuing...')\r\n\r\n# Do this instead\r\ndirectkeys.wait('space')\r\nprint('space was pressed, continuing...')\r\n```\r\n\r\n### Repeatedly waiting for a key press\r\n\r\n```py\r\nimport directkeys\r\n\r\n# Don't do this!\r\n#\r\n#while True:\r\n# if directkeys.is_pressed('space'):\r\n# print('space was pressed!')\r\n#\r\n# This will use 100% of your CPU and print the message many times.\r\n\r\n# Do this instead\r\nwhile True:\r\n directkeys.wait('space')\r\n print('space was pressed! Waiting on it again...')\r\n\r\n# or this\r\ndirectkeys.add_hotkey('space', lambda: print('space was pressed!'))\r\ndirectkeys.wait()\r\n```\r\n\r\n### Invoking code when an event happens\r\n\r\n```py\r\nimport directkeys\r\n\r\n# Don't do this! This will call `print('space')` immediately then fail when the key is actually pressed.\r\n#directkeys.add_hotkey('space', print('space was pressed'))\r\n\r\n# Do this instead\r\ndirectkeys.add_hotkey('space', lambda: print('space was pressed'))\r\n\r\n# or this\r\ndef on_space():\r\n print('space was pressed')\r\ndirectkeys.add_hotkey('space', on_space)\r\n\r\n# or this\r\nwhile True:\r\n # Wait for the next event.\r\n event = directkeys.read_event()\r\n if event.event_type == directkeys.KEY_DOWN and event.name == 'space':\r\n print('space was pressed')\r\n```\r\n\r\n### 'Press any key to continue'\r\n\r\n```py\r\n# Don't do this! The `keyboard` module is meant for global events, even when your program is not in focus.\r\n#import directkeys\r\n#print('Press any key to continue...')\r\n#directkeys.get_event()\r\n\r\n# Do this instead\r\ninput('Press enter to continue...')\r\n\r\n# Or one of the suggestions from here\r\n# https://stackoverflow.com/questions/983354/how-to-make-a-script-wait-for-a-pressed-key\r\n```\r\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "A modern and robust keyboard hooking and simulation library for Windows and Linux, focusing on low-level control.",
"version": "1.0.0",
"project_urls": {
"Homepage": "https://github.com/WigoWigo10/keyboard"
},
"split_keywords": [
"directkeys",
"keyboard",
"hook",
"simulate",
"hotkey",
"low-level",
"win32",
"sendinput"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "75feb75e1f02925b999281e40d3f9bf94e93d8e72c58cfb34033aac0546cfbe9",
"md5": "ac0ec4fcea3a0258c923589a402a3fc0",
"sha256": "c60c1ee8a4d62d8da6a2e2fa506468dc6bc3941015fb7d23751237b36d27d99c"
},
"downloads": -1,
"filename": "directkeys-1.0.0-py3-none-any.whl",
"has_sig": false,
"md5_digest": "ac0ec4fcea3a0258c923589a402a3fc0",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": null,
"size": 55876,
"upload_time": "2025-10-11T19:49:23",
"upload_time_iso_8601": "2025-10-11T19:49:23.089999Z",
"url": "https://files.pythonhosted.org/packages/75/fe/b75e1f02925b999281e40d3f9bf94e93d8e72c58cfb34033aac0546cfbe9/directkeys-1.0.0-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "ec5e34be562457584a76046d79eaa962e1fd00113d92a49d991c77064a1b2db8",
"md5": "8d89d307871085dd84ba6a74b5de15c2",
"sha256": "f3aed8d054370c6050d229f120325676ebef2add90e12f844158b9771cd46134"
},
"downloads": -1,
"filename": "directkeys-1.0.0.tar.gz",
"has_sig": false,
"md5_digest": "8d89d307871085dd84ba6a74b5de15c2",
"packagetype": "sdist",
"python_version": "source",
"requires_python": null,
"size": 68558,
"upload_time": "2025-10-11T19:49:24",
"upload_time_iso_8601": "2025-10-11T19:49:24.623128Z",
"url": "https://files.pythonhosted.org/packages/ec/5e/34be562457584a76046d79eaa962e1fd00113d92a49d991c77064a1b2db8/directkeys-1.0.0.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-10-11 19:49:24",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "WigoWigo10",
"github_project": "keyboard",
"travis_ci": false,
"coveralls": true,
"github_actions": false,
"lcname": "directkeys"
}