directkeys 1.0.0
A modern and robust keyboard hooking and simulation library for Windows and Linux, focusing on low-level control.
License: MIT
Keywords: directkeys keyboard hook simulate hotkey low-level win32 sendinput


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
```