Code Monkey home page Code Monkey logo

keyboard's Introduction

This project is currently unmaintained. It works for many cases, and I wish to pick it up again in the future, but you might encounter some friction and limited features using it.



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 and play, 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 (pip install mouse).

Usage

Install the PyPI package:

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 into your project folder.

Then check the API docs below to see what features are available.

Example

Use as library:

import keyboard

keyboard.press_and_release('shift+s, space')

keyboard.write('The quick brown fox jumps over the lazy dog.')

keyboard.add_hotkey('ctrl+shift+a', print, args=('triggered', 'hotkey'))

# Press PAGE UP then PAGE DOWN to type "foobar".
keyboard.add_hotkey('page up, page down', lambda: keyboard.write('foobar'))

# Blocks until you press esc.
keyboard.wait('esc')

# Record events until 'esc' is pressed.
recorded = keyboard.record(until='esc')
# Then replay back at three times the speed.
keyboard.play(recorded, speed_factor=3)

# Type @@ then press space to replace with abbreviation.
keyboard.add_abbreviation('@@', '[email protected]')

# Block forever, like `while True`.
keyboard.wait()

Use as standalone module:

# 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
  • Media keys on Linux may appear nameless (scan-code only) or not at all. #20
  • Key suppression/blocking only available on Windows. #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

import keyboard
keyboard.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
keyboard.wait()

# or this
import time
while True:
    time.sleep(1000000)

Waiting for a key press one time

import keyboard

# Don't do this! This will use 100% of your CPU until you press the key.
#
#while not keyboard.is_pressed('space'):
#    continue
#print('space was pressed, continuing...')

# Do this instead
keyboard.wait('space')
print('space was pressed, continuing...')

Repeatedly waiting for a key press

import keyboard

# Don't do this!
#
#while True:
#    if keyboard.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:
    keyboard.wait('space')
    print('space was pressed! Waiting on it again...')

# or this
keyboard.add_hotkey('space', lambda: print('space was pressed!'))
keyboard.wait()

Invoking code when an event happens

import keyboard

# Don't do this! This will call `print('space')` immediately then fail when the key is actually pressed.
#keyboard.add_hotkey('space', print('space was pressed'))

# Do this instead
keyboard.add_hotkey('space', lambda: print('space was pressed'))

# or this
def on_space():
    print('space was pressed')
keyboard.add_hotkey('space', on_space)

# or this
while True:
    # Wait for the next event.
    event = keyboard.read_event()
    if event.event_type == keyboard.KEY_DOWN and event.name == 'space':
        print('space was pressed')

'Press any key to continue'

# Don't do this! The `keyboard` module is meant for global events, even when your program is not in focus.
#import keyboard
#print('Press any key to continue...')
#keyboard.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

API

Table of Contents

= 'down'
= 'up'

[source]

= {'alt', 'alt gr', 'ctrl', 'left alt', 'left ctrl', 'left shift', 'left windows', 'right alt', 'right ctrl', 'right shift', 'right windows', 'shift', 'windows'}
= {'alt', 'ctrl', 'shift', 'windows'}
= '0.13.5'

[source]

Returns True if key is a scan code or name of a modifier key.

[source]

Returns a list of scan codes associated with this key (name or scan code).

[source]

Parses a user-provided hotkey into nested tuples representing the parsed structure, with the bottom values being lists of scan codes. Also accepts raw scan codes, which are then wrapped in the required number of nestings.

Example:

parse_hotkey("alt+shift+a, alt+b, c")
#    Keys:    ^~^ ^~~~^ ^  ^~^ ^  ^
#    Steps:   ^~~~~~~~~~^  ^~~~^  ^

# ((alt_codes, shift_codes, a_codes), (alt_codes, b_codes), (c_codes,))

[source]

Sends OS events that perform the given hotkey hotkey.

  • hotkey can be either a scan code (e.g. 57 for space), single key (e.g. 'space') or multi-key, multi-step hotkey (e.g. 'alt+F4, enter').
  • do_press if true then press events are sent. Defaults to True.
  • do_release if true then release events are sent. Defaults to True.
send(57)
send('ctrl+alt+del')
send('alt+F4, enter')
send('shift+s')

Note: keys are released in the opposite order they were pressed.

[source]

Presses and holds down a hotkey (see send).

[source]

Releases a hotkey (see send).

[source]

Returns True if the key is pressed.

is_pressed(57) #-> True
is_pressed('space') #-> True
is_pressed('ctrl+space') #-> True

[source]

Calls the provided function in a new thread after waiting some time. Useful for giving the system some time to process an event, without blocking the current execution flow.

[source]

Installs a global listener on all available keyboards, invoking callback each time a key is pressed or released.

The event passed to the callback is of type keyboard.KeyboardEvent, with the following attributes:

  • name: an Unicode representation of the character (e.g. "&") or description (e.g. "space"). The name is always lower-case.
  • scan_code: number representing the physical key, e.g. 55.
  • time: timestamp of the time the event occurred, with as much precision as given by the OS.

Returns the given callback for easier development.

[source]

Invokes callback for every KEY_DOWN event. For details see hook.

[source]

Invokes callback for every KEY_UP event. For details see hook.

[source]

Hooks key up and key down events for a single key. Returns the event handler created. To remove a hooked key use unhook_key(key) or unhook_key(handler).

Note: this function shares state with hotkeys, so clear_all_hotkeys affects it as well.

[source]

Invokes callback for KEY_DOWN event related to the given key. For details see hook.

[source]

Invokes callback for KEY_UP event related to the given key. For details see hook.

[source]

Removes a previously added hook, either by callback or by the return value of hook.

[source]

Removes all keyboard hooks in use, including hotkeys, abbreviations, word listeners, recorders and waits.

[source]

Suppresses all key events of the given key, regardless of modifiers.

[source]

Whenever the key src is pressed or released, regardless of modifiers, press or release the hotkey dst instead.

[source]

Parses a user-provided hotkey. Differently from parse_hotkey, instead of each step being a list of the different scan codes for each key, each step is a list of all possible combinations of those scan codes.

[source]

Invokes a callback every time a hotkey is pressed. The hotkey must be in the format ctrl+shift+a, s. This would trigger when the user holds ctrl, shift and "a" at once, releases, and then presses "s". To represent literal commas, pluses, and spaces, use their names ('comma', 'plus', 'space').

  • args is an optional list of arguments to passed to the callback during each invocation.
  • suppress defines if successful triggers should block the keys from being sent to other programs.
  • timeout is the amount of seconds allowed to pass between key presses.
  • trigger_on_release if true, the callback is invoked on key release instead of key press.

The event handler function is returned. To remove a hotkey call remove_hotkey(hotkey) or remove_hotkey(handler). before the hotkey state is reset.

Note: hotkeys are activated when the last key is pressed, not released. Note: the callback is executed in a separate thread, asynchronously. For an example of how to use a callback synchronously, see wait.

Examples:

# Different but equivalent ways to listen for a spacebar key press.
add_hotkey(' ', print, args=['space was pressed'])
add_hotkey('space', print, args=['space was pressed'])
add_hotkey('Space', print, args=['space was pressed'])
# Here 57 represents the keyboard code for spacebar; so you will be
# pressing 'spacebar', not '57' to activate the print function.
add_hotkey(57, print, args=['space was pressed'])

add_hotkey('ctrl+q', quit)
add_hotkey('ctrl+alt+enter, space', some_callback)

[source]

Removes a previously hooked hotkey. Must be called with the value returned by add_hotkey.

[source]

Removes all keyboard hotkeys in use, including abbreviations, word listeners, recorders and waits.

[source]

Whenever the hotkey src is pressed, suppress it and send dst instead.

Example:

remap('alt+w', 'ctrl+up')

[source]

Builds a list of all currently pressed scan codes, releases them and returns the list. Pairs well with restore_state and restore_modifiers.

[source]

Given a list of scan_codes ensures these keys, and only these keys, are pressed. Pairs well with stash_state, alternative to restore_modifiers.

[source]

Like restore_state, but only restores modifier keys.

[source]

Sends artificial keyboard events to the OS, simulating the typing of a given text. Characters not available on the keyboard are typed as explicit unicode characters using OS-specific functionality, such as alt+codepoint.

To ensure text integrity, all currently pressed keys are released before the text is typed, and modifiers are restored afterwards.

  • delay is the number of seconds to wait between keypresses, defaults to no delay.
  • restore_state_after can be used to restore the state of pressed keys after the text is typed, i.e. presses the keys that were released at the beginning. Defaults to True.
  • exact forces typing all characters as explicit unicode (e.g. alt+codepoint or special events). If None, uses platform-specific suggested value.

[source]

Blocks the program execution until the given hotkey is pressed or, if given no parameters, blocks forever.

[source]

Returns a string representation of hotkey from the given key names, or the currently pressed keys if not given. This function:

  • normalizes names;
  • removes "left" and "right" prefixes;
  • replaces the "+" key name with "plus" to avoid ambiguity;
  • puts modifier keys first, in a standardized order;
  • sort remaining keys;
  • finally, joins everything with "+".

Example:

get_hotkey_name(['+', 'left ctrl', 'shift'])
# "ctrl+shift+plus"

[source]

Blocks until a keyboard event happens, then returns that event.

[source]

Blocks until a keyboard event happens, then returns that event's name or, if missing, its scan code.

[source]

Similar to read_key(), but blocks until the user presses and releases a hotkey (or single key), then returns a string representing the hotkey pressed.

Example:

read_hotkey()
# "ctrl+shift+p"

[source]

Given a sequence of events, tries to deduce what strings were typed. Strings are separated when a non-textual key is pressed (such as tab or enter). Characters are converted to uppercase according to shift and capslock status. If allow_backspace is True, backspaces remove the last character typed.

This function is a generator, so you can pass an infinite stream of events and convert them to strings in real time.

Note this functions is merely an heuristic. Windows for example keeps per- process keyboard state such as keyboard layout, and this information is not available for our hooks.

get_type_strings(record()) #-> ['This is what', 'I recorded', '']

[source]

Starts recording all keyboard events into a global variable, or the given queue if any. Returns the queue of events and the hooked function.

Use stop_recording() or unhook(hooked_function) to stop.

[source]

Stops the global recording of events and returns a list of the events captured.

[source]

Records all keyboard events from all keyboards until the user presses the given hotkey. Then returns the list of events recorded, of type keyboard.KeyboardEvent. Pairs well with play(events).

Note: this is a blocking function. Note: for more details on the keyboard hook and events see hook.

[source]

Plays a sequence of recorded events, maintaining the relative time intervals. If speed_factor is <= 0 then the actions are replayed as fast as the OS allows. Pairs well with record().

Note: the current keyboard state is cleared at the beginning and restored at the end of the function.

[source]

Invokes a callback every time a sequence of characters is typed (e.g. 'pet') and followed by a trigger key (e.g. space). Modifiers (e.g. alt, ctrl, shift) are ignored.

  • word the typed text to be matched. E.g. 'pet'.
  • callback is an argument-less function to be invoked each time the word is typed.
  • triggers is the list of keys that will cause a match to be checked. If the user presses some key that is not a character (len>1) and not in triggers, the characters so far will be discarded. By default the trigger is only space.
  • match_suffix defines if endings of words should also be checked instead of only whole words. E.g. if true, typing 'carpet'+space will trigger the listener for 'pet'. Defaults to false, only whole words are checked.
  • timeout is the maximum number of seconds between typed characters before the current word is discarded. Defaults to 2 seconds.

Returns the event handler created. To remove a word listener use remove_word_listener(word) or remove_word_listener(handler).

Note: all actions are performed on key down. Key up events are ignored. Note: word matches are case sensitive.

[source]

Removes a previously registered word listener. Accepts either the word used during registration (exact string) or the event handler returned by the add_word_listener or add_abbreviation functions.

[source]

Registers a hotkey that replaces one typed text with another. For example

add_abbreviation('tm', u'™')

Replaces every "tm" followed by a space with a ™ symbol (and no space). The replacement is done by sending backspace events.

  • match_suffix defines if endings of words should also be checked instead of only whole words. E.g. if true, typing 'carpet'+space will trigger the listener for 'pet'. Defaults to false, only whole words are checked.
  • timeout is the maximum number of seconds between typed characters before the current word is discarded. Defaults to 2 seconds.

For more details see add_word_listener.

[source]

Given a key name (e.g. "LEFT CONTROL"), clean up the string and convert to the canonical representation (e.g. "left ctrl") if one is known.

keyboard's People

Contributors

arainflake avatar ash1sh27 avatar avasam avatar badtyprr avatar bluehephaestus avatar boppreh avatar crazyquark avatar danmossa avatar duianto avatar enteleform avatar foodforarabbit avatar glitchassassin avatar gloglas avatar haoflynet avatar iliazeus avatar luizzeroxis avatar massongit avatar narendra-neerukonda avatar peterxu30 avatar prim avatar schldwcht avatar songyang1995 avatar tgoins avatar timgates42 avatar trakjohnson avatar vladimirv99 avatar vonlisboa avatar wooble avatar xoviat avatar yemreak avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

keyboard's Issues

nothing happens

hi, i am python newbie, and is very dificult to me understand how to run this program, so, i create a executable file on linux called k3y like this

#!/usr/bin/python
# coding: latin-1

import keyboard

# Press PAGE UP then PAGE DOWN to type "foobar".
keyboard.add_hotkey('page up, page down', lambda: keyboard.write('foobar'))

keyboard.add_hotkey('ctrl+q', quit)
keyboard.add_hotkey('ctrl+alt+enter, space', u'some_callback')
keyboard.add_abbreviation('tm', u'™')
keyboard.add_abbreviation('3n', u'el3ctron') 

so, i executed on my command line ./k3y
it runs showing no error,
but when i do some abreviation (for example writting in another window 3n), or pressing some hot key ('page up, page down') nothing happens! i do not know if i am doing something wrong. :(

Linux: multiple keyboards

I had some problems getting keyboard events and found out that the problem was caused by these lines (nixkeyboard.py, line 65):

paths = glob('/dev/input/by-path/*-event-kbd')
print(paths)
if paths:
    device = EventDevice(paths[0])

This code assumes that there's only one input device matching *-event-kbd. If there are multiple matches, it selects the first. However, there are three matches on my machine:

paths = ['/dev/input/by-path/pci-0000:00:14.0-usb-0:3.2.1:1.1-event-kbd',  # ???
         '/dev/input/by-path/pci-0000:00:14.0-usb-0:3.2.1:1.0-event-kbd',  # usb keyboard
         '/dev/input/by-path/platform-i8042-serio-0-event-kbd']  # laptop keyboard

I tested that the second device is my usb keyboard and the third device is the keyboard of my laptop. I don't know about the first device.

I think the library should read input from all keyboard input devices (or even better, allow the user to specify which devices to read from). What do you think?

Source package doesn't include "CHANGES.md"

The source ZIP in PyPI doesn't include the file CHANGES.md, which makes setup.py fail in the following line:

last_version = re.search('(\d+(?:\.\d+)+)', open('CHANGES.md').read()).group(1)

import keyboard error

 File "c:\GG-Python\WingProj\hupai\kbhit.py", line 5, in
import keyboard
File "C:\GG-Python\Anaconda\Lib\site-packages\keyboard__init__.py", line 1, in
from .keyboard import *
File "C:\GG-Python\Anaconda\Lib\site-packages\keyboard\keyboard.py", line 8, in
import keyboard.winkeyboard as os_keyboard

ImportError: No module named winkeyboard

Can't map some keys

Hi, thanks for this library, I'm trying to make use of it to create a simple custom hotkey "alias". I'm on a MacBook Air running Linux (Gentoo).

import keyboard
import time

keyboard.clear_all_hotkeys()

keyboard.add_hotkey('win+c', lambda: keyboard.send('ctrl+c'))
keyboard.add_hotkey('win+v', lambda: keyboard.send('ctrl+v'))

keyboard.add_hotkey('win+l', lambda: keyboard.send('ctrl+l'))
keyboard.add_hotkey('win+e', lambda: keyboard.send('ctrl+l'))

while True:
    time.sleep(10)

On the script above, win+l and win+e are calling the same keyboard hotkey but only win+e works. I'm hitting those hotkeys on Chrome browser.

If I change those mappings to a debugger output:

keyboard.add_hotkey('win+c', lambda: print('ctrl+c'))
keyboard.add_hotkey('win+v', lambda: print('ctrl+v'))

keyboard.add_hotkey('win+l', lambda: print('ctrl+l'))
keyboard.add_hotkey('win+e', lambda: print('ctrl+l'))

I do see the output on the console. Do you have any idea what could be cause these events to not be correctly processed by chrome?

P.S.: I don't think it's relative to Chrome, as the same hotkeys don't work on other applications (e.g. termite).

Support for key suppression

Right now all events report after-the-fact. It should be possible to suppress keys, keeping them from being processed by applications down the line. This allows users to create global hotkeys without affecting the focused application, for example.

This is possible in Windows, but would require moving the hotkey processing back into the hook.

Linux seems to be trickier. Maybe relying on X, like https://github.com/alols/xcape ?

Finally, extreme care must be taken to not introduce input lag. Because all hotkeys will be processed in the main thread, blocking the event they analyze, it would be too easy to add precious milliseconds to every key press, which is not acceptable.

Need help to configure

Iam trying to set .press() setup, without lucky.

I want something like that, when I prest alt+g then holds down F8 key until I press 'esc'

Is that possible?

Root required on Linux

The requirement of root access won't work for a large number of applications.

I didn't look through what made that a requirement, but it looks like ensure_root is littered all over the code base for a posix environment.

Somewhat related - I wasn't able to setup a virtualenv properly because of this requirement.

Linux: No keyboard found on Thinkpad T440s

On this this laptop (Lenovo Thinkpad T440s, no external keyboard, running Arch Linux), no matching keyboards are founds, so I get ImportError: No keyboard files found (/dev/input/by-path/*-event-kbd).

My /dev/input/by-path directory has only:

lrwxrwxrwx 1 root root  10 Aug  6 22:40 pci-0000:00:14.0-usb-0:8:1.0-event -> ../event13
lrwxrwxrwx 1 root root   9 Aug  6 22:40 platform-pcspkr-event-spkr -> ../event5
lrwxrwxrwx 1 root root   9 Aug  6 22:40 platform-thinkpad_acpi-event -> ../event4

by-id is just one:

lrwxrwxrwx 1 root root  10 Aug  6 22:40 usb-J30E9SCWZ_Integrated_Camera-event-if00 -> ../event13

xinput list reports:

⎡ Virtual core pointer                          id=2    [master pointer  (3)]
⎜   ↳ Virtual core XTEST pointer                id=4    [slave  pointer  (2)]
⎜   ↳ SynPS/2 Synaptics TouchPad                id=11   [slave  pointer  (2)]
⎜   ↳ TPPS/2 IBM TrackPoint                     id=12   [slave  pointer  (2)]
⎣ Virtual core keyboard                         id=3    [master keyboard (2)]
    ↳ Virtual core XTEST keyboard               id=5    [slave  keyboard (3)]
    ↳ Power Button                              id=6    [slave  keyboard (3)]
    ↳ Video Bus                                 id=7    [slave  keyboard (3)]
    ↳ Sleep Button                              id=8    [slave  keyboard (3)]
    ↳ Integrated Camera                         id=9    [slave  keyboard (3)]
    ↳ AT Translated Set 2 keyboard              id=10   [slave  keyboard (3)]
    ↳ ThinkPad Extra Buttons                    id=13   [slave  keyboard (3)]

The AT Translated Set 2 keyboard (id 10) is the one that shows activity on xinput test 10.

xinput list-props 10:

Device 'AT Translated Set 2 keyboard':
        Device Enabled (139):   1
        Coordinate Transformation Matrix (141): 1.000000, 0.000000, 0.000000, 0.000000, 1.000000, 0.000000, 0.000000, 0.000000, 1.000000
        Device Product ID (260):        1, 1
        Device Node (261):      "/dev/input/event0"

Is there any way this library can hook into the keyboard on this system? Let me know if I can give any more details!

Support for dead keys

Linux gives this wonderfully detailed mapping of all dead keys and what happens when you combine them with different letters. But the library completely ignores it.

Supporting dead keys would give more accurate get_typed_strings and write.

KeyError using 'win' modifier

It looks like there is an issue in _keyboard_event.py with canonical_names mapping "win" to "windows". In the to_scan_code dictionary, there is only "left windows" and "right windows".

Traceback (most recent call last):
File "C:\Python34\lib\site-packages\keyboard_generic.py", line 23, in invoke_handlers
if handler(event):
File "C:\Python34\lib\site-packages\keyboard_init_.py", line 255, in handler
unexpected = not any(matches(event, part) for part in steps[state.step])
File "C:\Python34\lib\site-packages\keyboard_init_.py", line 255, in
unexpected = not any(matches(event, part) for part in steps[state.step])
File "C:\Python34\lib\site-packages\keyboard_init_.py", line 132, in matches
return matched_name or _os_keyboard.map_char(name)[0] == event.scan_code
File "C:\Python34\lib\site-packages\keyboard_winkeyboard.py", line 431, in map_char
return -media_name_to_vk(name), []
File "C:\Python34\lib\site-packages\keyboard_winkeyboard.py", line 437, in media_name_to_vk
raise ValueError('Key name {} is not mapped to any known key.'.format(repr(name)))
ValueError: Key name 'windows' is not mapped to any known key.
Traceback (most recent call last):
File "C:\Python34\lib\site-packages\keyboard_winkeyboard.py", line 428, in map_char
scan_code, shift = to_scan_code[name]
KeyError: 'windows'

Code used:

keyboard.add_hotkey('win+comma', lambda e: keyboard.send('volume down'))

Support for hardware changes on Linux

Right now if a user plugs or unplugs a keyboard on Linux the library won't realize. Specially now that Linux correctly reports the device id, it should be possible to update hardware changes.

Windows gives this for free.

Using multimedia keys (volume up/down)?

Is it possible to simulate using these keys I don't have a multimedia keyboard actually attached? How would I go about finding the code to send? I currently am using an AutoHotKey script for it but would love to replace it with a python script instead.

EDIT: I'm on Windows.

Using keyboard on a headless device (no keyboard attached)

Hi and thanks for this useful library!

I've been evaluating it for a while and everything works perfectly until today when I tried it without a keyboard attached (as I will use it).

ImportError: No keyboard files found (/dev/input/by-path/*-event-kbd).

Must I have a keyboard attached or is there anything I can do to get around it?

Multimedia keys on Linux

Linux doesn't seem to emit any events for multimedia keys. In Windows they were already weird because of their null scan code, but in Linux literally nothing happens.

This should be fixed somehow.

Windows support

Hi,

This pure-python, cross-platform lib is quite impressive. It could help a lot on workstations where adding stuff is severely restricted (ie no pip, etc.).

One thing I'm looking for is to reproduce (at least partly) the abbreviation expansion functionality found in Autohotkey (among others).
This replaces text patterns as you type, without hotkeys (ie., type 'tm" followed by space and its gets replaced by a trademark symbol for example).

I have not been able to do this using the add_hotkey method (which is probably normal).
Could there be a way to achieve it using the lower-level functions ?

TIA,
fp

Permission denied and not receiving events (Ubuntu 14.04.1)

Running this code:

import keyboard


keyboard.add_hotkey('f4', lambda: print('f4'))
keyboard.add_hotkey('f5', lambda: print('f5'))
keyboard.add_hotkey('f6', lambda: print('f6'))

keyboard.wait('esc')

Results in the following in the stderr:

Permission denied (/dev/input/by-path/platform-i8042-serio-0-event-kbd). You must be sudo to access global events.

Also the callbacks are never executed.

Let me know if I can give more details.

Duplicate keypad codes

keyboard currently maps certain numpad keys to the same key code as other function keys. Examples are num * and print screen, num 6 and right, num 9 and page up, etc.

When I call press_and_release('print screen'), instead of copying the screen to the clipboard, I get a * character. When I call press_and_release('num 8'), I get an up-arrow keypress instead. (Note that if I use keypad 8 it prints an 8 as expected.)

Could you clarify how this behavior should work? (Below I've included the output of the _os_keyboard.to_scan_code dict for your reference.)

{u"'": (40, False),
u'+': (78, False),
u',': (51, False),
u'-': (12, False),
u'.': (52, False),
u'/': (53, False),
u'0': (11, False),
u'1': (2, False),
u'2': (3, False),
u'3': (4, False),
u'4': (5, False),
u'5': (6, False),
u'6': (7, False),
u'7': (8, False),
u'8': (9, False),
u'9': (10, False),
u';': (39, False),
u'<00>': (84, False),
u'=': (13, False),
u'[': (26, False),
u'\\': (43, False),
u']': (27, False),
u'`': (41, False),
u'a': (30, False),
u'alt': (56, False),
'alt gr': 541,
u'b': (48, False),
u'backspace': (14, False),
u'break': (70, False),
u'c': (46, False),
u'caps lock': (58, False),
u'ctrl': (29, False),
u'd': (32, False),
u'delete': (83, False),
u'down': (80, False),
u'e': (18, False),
u'end': (79, False),
u'enter': (28, False),
u'esc': (1, False),
u'f': (33, False),
u'f1': (59, False),
u'f10': (68, False),
u'f11': (87, False),
u'f12': (88, False),
u'f13': (124, False),
u'f14': (125, False),
u'f15': (126, False),
u'f16': (127, False),
u'f2': (60, False),
u'f3': (61, False),
u'f4': (62, False),
u'f5': (63, False),
u'f6': (64, False),
u'f7': (65, False),
u'f8': (66, False),
u'f9': (67, False),
u'g': (34, False),
u'h': (35, False),
u'help': (86, False),
u'home': (71, False),
u'i': (23, False),
u'insert': (82, False),
u'j': (36, False),
u'k': (37, False),
u'l': (38, False),
u'left': (75, False),
u'left windows': (91, False),
u'm': (50, False),
'menu': (93, False),
u'n': (49, False),
u'num *': (55, False),
u'num +': (78, False),
u'num -': (74, False),
u'num /': (53, False),
u'num 0': (82, False),
u'num 1': (79, False),
u'num 2': (80, False),
u'num 3': (81, False),
u'num 4': (75, False),
u'num 5': (76, False),
u'num 6': (77, False),
u'num 7': (71, False),
u'num 8': (72, False),
u'num 9': (73, False),
u'num del': (83, False),
u'num enter': (28, False),
u'num lock': (69, False),
u'o': (24, False),
u'p': (25, False),
u'page down': (81, False),
u'page up': (73, False),
u'pause': (69, False),
'print screen': (55, False),
u'q': (16, False),
u'r': (19, False),
u'right': (77, False),
u'right alt': (56, False),
u'right ctrl': (29, False),
u'right shift': (54, False),
u'right windows': (92, False),
u's': (31, False),
u'scroll lock': (70, False),
u'shift': (42, False),
u'space': (57, False),
u'sys req': (84, False),
u't': (20, False),
u'tab': (15, False),
u'u': (22, False),
u'up': (72, False),
u'v': (47, False),
u'w': (17, False),
u'x': (45, False),
u'y': (21, False),
u'z': (44, False)}

Report device id on Windows

Linux already has this.

Device information is not included in the hook we are using, which complicates things. Raw Input seems to provide this, but it doesn't include the virtual key codes we use to map most of the key names and keypad status.

There should be some kind of device information on event.device.

Note: https://github.com/me2d13/luamacros seems to do this.

Use a build server for automated testing?

This library advertises python 2 compatibility but it looks like the latest release had zero testing on python 2, since it doesn't work at all.

I tried setting up travis-ci to run keyboard's test suite on python 2 and 3, and got it working pretty easily. Check it out: https://github.com/Hyphenated-integrations/keyboard/commits/master

https://travis-ci.org/Hyphenated-integrations/keyboard

When I revert the recent fix to the py2 issue, the py2 travis build fails! Cool! I don't know why it times out rather than giving an error message, but that's not a huge deal. It still means the code is broken.

travis-ci is free for open source projects, so: consider doing this officially to help make fewer bad releases?

Report accurate state of * lock keys

Caps lock, num lock, scroll lock are all toggle modifiers, so if their state is unexpected at the start of the program it'll never be fixed. There should be a way to poll their actual status.

This may be expanded to include other modifiers, so the library starts more ready.

This may require update the functions that handle modifier keys, to take into account 'toggle' keys too.

Library don't record keys on Ubuntu 16.04 LTS

When I use the function keyboard.record() or when I try to make a hook using keyboard.on_press(), it simply don't detect the pressed keys.
The keyboard.write() function works fine.
On Windows 10, the same code seems to work fine.
P.S.: I ran the code as superuser

keyboard hook in windows partially stops working

Hi there, having a weird issue here: Once I start a fullscreen game on my Windows VM that uses synergy to broadcast mouse and keyboard to the second monitor which runs the Host Linux system, my small python script I use for push to talk has a slight issue.
Normally I can use the hook to safely get the key pressed every time, no matter where the mouse is at or which window on which system is focused. The keypresses when the game has started still work on the windows vm (where the keyboard and mouse are connected at) but once I move the mouse to the other screen they stop working. This is the simple script I use (client and server, using UDP):
https://gist.github.com/Keridos/28fb408df82cae3b6b259e05f666b314

X Inputs

Would you be interested in an X-based global hotkey capture? I wrote (most of) one in an effort to make a global-hotkey-library before I found this project. It has a dependency on python-xlib, but that's preferable to having to run as root. Root mode could still be used as a fallback if the xlib package isn't available, still keeping the "zero dependency" guarantee.

Obviously, my code would need to be adapted to your architecture, but I don't think that should be too hard.

Linux win key causes keyboard module throw an exception.

Example program

import keyboard
import time
import logging
BINDS = []
BINDS.append(keyboard.add_hotkey("win", lambda: logging.error("pressed")))
while True:
    time.sleep(1)

Result when pressing win key

Exception in thread Thread-1:
Traceback (most recent call last):
  File "/home/mblizniak/repos/i3-pyswitch/3rd-party/kb/_nixkeyboard.py", line 94, in listen
    name = to_name[(scan_code, tuple(sorted(pressed_modifiers)))]
KeyError: (125, ())

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/lib/python3.5/threading.py", line 914, in _bootstrap_inner
    self.run()
  File "/usr/lib/python3.5/threading.py", line 862, in run
    self._target(*self._args, **self._kwargs)
  File "/home/mblizniak/repos/i3-pyswitch/3rd-party/kb/__init__.py", line 79, in listen
    _os_keyboard.listen(self.queue)
  File "/home/mblizniak/repos/i3-pyswitch/3rd-party/kb/_nixkeyboard.py", line 96, in listen
    name = to_name[(scan_code, ())]
KeyError: (125, ())

dumpkeys--keys-only.txt

The problem of running in root privileges

Hi, thanks for this useful library. I wrote a script to google the selected text when pressing the hot keys. After running it in root privileges, instead of opening my default web browser, it opens another one.

I added some codes to the script to drop the root privileges. Then the script worked perfectly.

uid = pwd.getpwnam('my_user_name')[2]
os.setuid(uid)

But it is possibly not a good idea to enter my user name. So is there another way to achieve this?

add_hotkey doesn't 'catch' keyboard event.

Basically, when I use add_hotkey to register a hotkey, I would expect it to receive the event and stop it from being passed over.
Although I'm not sure if its an issue, but I can't find anything about it in the README.

"Clear" AttributeError

When I try to define a hotkey "alt+shift+c", I get the following message:

('Error in keyboard hook: ', AttributeError("'list' object has no attribute 'clear'",))

I'm not immediately sure where this error is originating from, but it looks like the _keys_suppressed list in the KeyTable object in _suppress.py doesn't have a clear() method (perhaps it should be a set instead of a list?)

report a few errors in key mappings and some notes on Alt-Gr / ctrl+alt

Hi every one ! smart-useful-complete pure python ctypes project ! Wow !
Here are a few errors I got.
Your skills are definitely higher than mine, but here are a few notes, with "a fresh view".
A few tunings, and you will Hit mY keYbOarD !
Hope it helps.
Regards, Stanislas.

# THE FILE:

import keyboard
# version is recent keyboard-master, lundi 13 février 2017, 16:42:31
# console is the notepad++ python console, 
# an instance of scintilla editor, as any other editor buffer, supports print.
# This is a UTF-8-BOM, Windows file, on winxp sp3.

def end_bye():
    keyboard.unhook_all()
    console.write('keyboard.unhook_all')
    
# succes
keyboard.press_and_release('shift+s, space')
# succes
keyboard.write('The quick brown fox jumps over the lazy dog.')
# sucks
keyboard.add_hotkey('Space', lambda: console.write('space was pressed') )
# sucks
keyboard.wait('a')

# EOF

# THE ERRORS OUTPUT:

keyboard.add_hotkey('Space', print, args=['space was pressed'])
SyntaxError: invalid syntax      ^

    keyboard.add_hotkey('Space', lambda: print 'space was pressed' )
SyntaxError: invalid syntax                  ^


keyboard.wait('a')
Traceback (most recent call last):
  File "...\hk\keyboard_test.py", line 36, in <module>
    keyboard.wait('a')
  File "C:\Python27\lib\site-packages\keyboard\__init__.py", line 652, in wait
    wait()
  File "C:\Python27\lib\site-packages\keyboard\__init__.py", line 639, in wait
    return q.get(timeout=1)
  File "C:\Python27\Lib\Queue.py", line 177, in get
    self.not_empty.wait(remaining)
  File "C:\Python27\Lib\threading.py", line 355, in wait
    remaining = endtime - _time()
KeyboardInterrupt

the script has properly stopped running,
but has printed "€€" , once at the caret position at which the script was launched, and then randomly through several other opened files in the notepad++ editor ... all along the same error.
let's talk about "€" later ...

also:

in: _keyboard_event.py :

    canonical_names = { ...,
                     'num add': '+',
                     'num plus': '+',
                     'num minus': '+',       # oops
                     'num sub': '-' , 

And in: _winkeyboard.py, from_virtual_key={... 0xbb: ('=', False), doesn't seem to exist , mapped to : _keyboard_event.py canonical_names = { ..., 'equal': '=', ... } ?

Other implementation use this k:v on a different purpose: watch for the alt-key-pressed state of a key, in the case of UI menus handling with a &MenuItem shortcut mapping.

There is an implementation of these crossed mappings between vk and ascii
representation in the "PythonWin" source code on github,and a shorter version too with fewer mappings.

Yet their mapping is incomplete, as it has a contextual purpose.
Yours aims to be wider, so nice !

Their logic is to parse vk as"ascii_not_shifted +-" (+-shifted)to be sure to end with no ambiguity (function parse_key_name(name)).
Ex: outputs of test2() in keycodes.py:

    Alt+/  ->  191,19  ->  Shift+Alt+:           '/' is detected as 'shift'+':'
    \      ->   56,15  ->  Ctrl+Alt+_          it couldn't match an event as 'alt-gr'+'_' ...

Also it separates the users logic from the implementation logic :
a silly example:
I want to set up a hk with the '/' symbol for my purpose, not the ':' symbol.
I think (hope) most people type'shift+:'without the intent to press this specific combination, they do because "this is the way it is to get '/' ", from the reptilian cognitive layer, almost like walking.
Though, 'ctrl+/' would be meaningful, ex. as an application hotkey, where the / holds the aim, however we do access to it. It is 'shift+:', you know it, could you hold that for my higher-level-of-abstraction ... ?
And this way, I am sure that both symbols will be available, as they should not
be mutually exclusive
, every char will be safe and glad to serve our most exquisite desires !

About alternate engraving

the "alternate-engraving" key and WM_SYSKEYDOWN :

in _winkeyboard.py,
         line~~300, ... alt_gr_scan_code = 541         # ???
         line~~121, WM_SYSKEYDOWN = 0x104 # Used for ALT key
         watch the results I get from a view on the events broadcasting :
         it is true for ( 'ctrl' , 'alt' , 'e' ), not for ( 'alt-gr' , 'e' ), on my winxp sp3

I don't see that as an inconsistency, just the complexity to be able to input more symbols than the number of keys we have on our keyboards. As the alt key served the UI menus fisrt, it is a way to have a kind of alternate-alt, that shares only a part of it's business with it's left sister, not as the ctrl and shift keys do, and usable with one finger only !!!
The more I used it, the more I loved that key. I was doing maths outside of latex : Autohothey was a big help to map contextually all my keys to utf-8 Greek and math symbols on alt-gr/ctrl+alt !
Then giving the users two different methods of input, one for the left-handlers, one for the others ( 'alt-gr' | 'ctrl'+'alt' ) over-adds to the complexity.

By the way, your unicode implementation is a really consistent piece of code to study, as it is still a pain for me to have a large view on it, a really, really nice good help.
Thanks a lot for the lesson .

VK_CONTROL   0x11
VK_MENU      0x12  :  alt     menu because it first gave access to menus, 
# note from WinUser.h :
# VK_L* & VK_R* - left and right Alt, Ctrl and Shift virtual keys.
# Used only as parameters to GetAsyncKeyState() and GetKeyState().
# No other API or message will distinguish left and right keys in this way.
#                     not so simple in fact ... alt-gr is the exception :
VK_LMENU     0xA4  :  alt
VK_RMENU     0xA5  :  alt-gr in the vk perspective, BUT NOT IN MESSAGING : 
                                    it gets broacasted as 'alt'+'mod_ctrl' 
                      and 'ctrl'+'mod_alt' yields the same result, as "€"

You can get a ?clear view of the mechanism in the exemples below:
two ways to get the Euro symbol '€' ( bad news for me, European : some have "the easy way" to make some, and convert it to '$' or '£' as fast as they can, far away from my home, under some coconut-tree ... ;-).

summary of the events sequence:

the details are below_below.

1)  typed ( 'alt-gr', 'e' )           2)  typed ( 'ctrl' , 'alt' , 'e' )
    event:                                event:
       kd  ctrl    NO MOD_KEY             syskd  MOD_KEY is VK_MENU 0x12, alt
       kd  alt     NO MOD_KEY                kd  ctrl    (+ mod_alt )
       kd  E                                 kd  E
       ch  €                                 ch  €
       ku  E                                 ku  E
    sysku  MOD_KEY is VK_CONTROL 0x11     sysku  MOD_KEY is VK_MENU 0x12, alt
       ku  alt     (+ mod_ctrl )             ku  ctrl    (+ mod_alt )

with a hotkeys dict like:

MOD_ALT     = 1 ;  MOD_CONTROL = 2
# key_k = 75                                   #  fires on:
my_hks = { 0 : ( 75, MOD_ALT             ),    #  'alt+k'
           1 : ( 75, MOD_ALT+MOD_CONTROL ) }   #  'ctrl+alt+k'  and  'alt-gr+k'

with hotkeys we don't care about checking the events details ... but it's far less powerful than what you are setting up on chars only, unicode included ! a blessing !

below below

details: 1) pressing ( 'alt-gr', 'e' ) to print the '€' euro sign :
<messages created-by="Winspector">                 <!-- 99.99% filtered ... -->
<message>
    <name>WM_KEYDOWN</name>
    <posted />
    <time>16:26:50.0468</time>
    <parameters>
        <parameter>Virtual Key: VK_CONTROL</parameter>  ctrl    NO MOD_KEY
    </parameters>                                       
</message>                                              
<message>                                               
    <name>WM_KEYDOWN</name>                             
    <posted />                                          
    <time>16:26:50.0468</time>                          
    <parameters>                                        
        <parameter>Virtual Key: VK_MENU</parameter>     alt     NO MOD_KEY
    </parameters>                                       
</message>                                                      
<message>                                               
    <name>WM_KEYDOWN</name>                             
    <posted />                                          
    <time>16:26:50.0515</time>                          
    <parameters>                                        
        <parameter>Virtual Key: E</parameter>           E
    </parameters>                                       
</message>                                              
<message>                                               
    <name>WM_CHAR</name>                                
    <posted />                                          
    <time>16:26:50.0515</time>                          
    <parameters>                                        
        <parameter>wParam: 0x000020ac</parameter>       €
        <parameter>lParam: 0x20120001</parameter>       
    </parameters>                                       
</message>                                              
<message>                                               
    <name>WM_KEYUP</name>
    <posted />                                          
    <time>16:26:50.0718</time>                          
    <parameters>                                        
        <parameter>Virtual Key: E</parameter>           E
    </parameters>                                       
</message>                                              
<message>                                               
    <name>WM_SYSKEYUP</name>                            
    <posted />                                          
    <time>16:26:51.0046</time>                          
    <parameters>                                        
        <parameter>wParam: 0x00000011</parameter>       MOD_KEY VK_CONTROL 0x11
        <parameter>lParam: 0xe01d0001</parameter>       ???
    </parameters>                                       
</message>                                              
<message>                                               
    <name>WM_KEYUP</name>                               
    <posted />                                          
    <time>16:26:51.0046</time>                          
    <parameters>                                        
        <parameter>Virtual Key: VK_MENU</parameter>     alt (+ mod_ctrl )
    </parameters>                                       
</message>

details: 2) same money, but using ( 'ctrl' , 'alt' , 'e' )
<message>
    <name>WM_SYSKEYDOWN</name>
    <posted />
    <time>15:30:54.0406</time>
    <parameters>
        <parameter>wParam: 0x00000012</parameter>     MOD_KEY VK_MENU 0x12 alt
        <parameter>lParam: 0x20380001</parameter>       
    </parameters>                                       
</message>                                              
<message>                                               
    <name>WM_KEYDOWN</name>                             
    <posted />                                          
    <time>15:30:54.0406</time>                          
    <parameters>                                        
        <parameter>Virtual Key: VK_CONTROL</parameter>  ctrl (+ mod_alt )
    </parameters>                                       
</message>                                              
<message>                                               
    <name>WM_KEYDOWN</name>                             
    <posted />                                          
    <time>15:30:55.0046</time>                          
    <parameters>                                        
        <parameter>Virtual Key: E</parameter>           E
    </parameters>                                       
</message>                                              
<message>                                               
    <name>WM_CHAR</name>                                
    <posted />                                          
    <time>15:30:55.0046</time>                 
    <parameters>                                        
        <parameter>wParam: 0x000020ac</parameter>       €
        <parameter>lParam: 0x20120001</parameter>       
    </parameters>                                       
</message>                                              
<message>                                               
    <name>WM_KEYUP</name>                               
    <posted />                                          
    <time>15:30:55.0218</time>                          
    <parameters>                                        
        <parameter>Virtual Key: E</parameter>           E
    </parameters>                                       
</message>                                              
<message>                                               
    <name>WM_SYSKEYUP</name>                            
    <posted />                                          
    <time>15:30:55.0328</time>                          
    <parameters>                                        
        <parameter>wParam: 0x00000012</parameter>     MOD_KEY VK_MENU 0x12 alt
        <parameter>lParam: 0xc0380001</parameter>       
    </parameters>                                       
</message>                                              
<message>                                               
    <name>WM_KEYUP</name>                               
    <posted />                                          
    <time>15:30:55.0328</time>                          
    <parameters>                                        
        <parameter>Virtual Key: VK_CONTROL</parameter>  ctrl (+ mod_alt )
    </parameters>
</message>

+==== The xml output is produced by Winspector

It is a pretty old freeware app from gipsysoft that runs fine under my winxp sp3. I didn't try it on a more recent system.
All the download links seem to be dead and it is a real pity / shame, as it is a really cool stuff, that mimics the Spy++ of Microsoft, aviable only with the commercial versions of VisualStudio.
I didn't use it for years, and that Alt-Gr stuff was bothering, so I gave an eye with it. I knew I would keep such a cool-stuff in some safe place, and could find the setup file of Winspector in a backup. I was lucky to get it a few years ago, from an Autohotkey forum. Those AHK addicts are deeply into the WinApi automation, and this tool was a must to peek into that complexity ... If you want, you can get it from my google-drive as a zipped file and happily watch your system events .... Note that the result of key-event-viewer.html are slightly different : it is handling Alt-Gr and Ctrl+Alt the same, and it is NOT THE REALITY : it doesn't report the WM_SYSKEYDOWN generated ! Winspector does ... unless that difference, we wouldn't need to ask ourselves such silly questions ... !

Winspector is poorely documented, so here is "a-short-how-to" :
Select a window, rightckick the item highlighted in the list, get "Messages" --> Messages_window: has an icon "traffic light" : pauses events capture on/off, an icon "save" ... saves to xml.
Right click Messages_window, get "Edit message filter", put the kept event in the right-side list. Be carefull: the msgs outputs will be filtered in the Messages_window, but it doesn`t apply filter to the results in memory, and it saves ALL events it catches : events captured during 3 key-press is already a big quantity of msgs, so, if you play with it, be sure to produce as few mouse moves and breathings as you can, be a good boy : mind the "traffic light", saving xml may look like hanging for freezing ? no, it just can be processing a huge xml file ... Enjoy !

# a quick filter script for the Large xml file :
import xml.etree.ElementTree as ET
file_in  = "messages3.xml"                  # same dir as script_file
file_out = "filtered_"+file_in
tree = ET.parse(file_in)                    # ASCII or use ET.XMLParser(enc...)
root = tree.getroot()
filter =  [ 'WM_SYSKEYDOWN' ,
            'WM_KEYDOWN'    ,
            'WM_CHAR'       ,
            'WM_KEYUP'      ,
            'WM_SYSKEYUP'   
            ]
for message in root.findall('message'):
    name = message.find('name').text
    if name not in filter:
        root.remove(message)
tree.write('filtered_messages.xml') # Result to an XML File

Once again, thank you for your this shared work and may the Force be with you ...

Alt Gr with Key throws Exception

When adding a hot-key with Alt Gr and a character, an exception is thrown.

Example:

keyboard.register_hotkey('alt gr+.', my_callback)

Exception occurs when pressing keys:

  Traceback (most recent call last):
  File "C:\Python27\lib\site-packages\keyboard\_generic.py", line 23, in invoke_handlers
    if handler(event):
  File "C:\Python27\lib\site-packages\keyboard\__init__.py", line 283, in handler
    unexpected = not any(matches(event, part) for part in steps[state.step])
  File "C:\Python27\lib\site-packages\keyboard\__init__.py", line 283, in <genexpr>
    unexpected = not any(matches(event, part) for part in steps[state.step])
  File "C:\Python27\lib\site-packages\keyboard\__init__.py", line 149, in matches
    return matched_name or _os_keyboard.map_char(normalized)[0] == event.scan_code
  File "C:\Python27\lib\site-packages\keyboard\_winkeyboard.py", line 444, in map_char
    scan_code, shift = to_scan_code[name]
TypeError: 'int' object is not iterable

'alt gr,.' isn't working ,too.

I found out that the configration map used to find scan-codes, does not return a tuple with Shift-Flag:

        from_scan_code[alt_gr_scan_code] = ['alt gr', 'alt gr']
        to_scan_code['alt gr'] = alt_gr_scan_code
    finally:
        tables_lock.release()

see Code

The following modification worked for me:

        to_scan_code['alt gr'] = alt_gr_scan_code, False

Hotkey action finishes before typed keys for hook.

I noticed strange behaviour in hotkey action finish. The example script i used:

#!python3
import keyboard
import threading
typing = False

def HookCallback(kbd_event: keyboard.KeyboardEvent):
    global typing
    print("Are programly typed: " + str(typing) + ", key: "+ kbd_event.name + ", event: " + kbd_event.event_type)

def hkAction():
    global typing
    typing = True
    print("Starting to typing...")
    keyboard.write("hello world!")
    typing = False
    print("Ended typing.")
    
keyboard.hook(HookCallback)
keyboard.register_hotkey('f7', hkAction)
keyboard.wait()

After you press F7, it will type pogrammatically the hello world! text, but also you will see the hook that prints the variable typing value which is always false, but it should be true when its pogrammatically types the hello world! text, how can this be solved? Are the hotkey action and hooks are queuing?

udp:

I also tried to set hook and register hotkey on different threads but got same result.

module import error

Python27\lib\site-packages\keyboard\mouse.py", line 5, in
import keyboard.winmouse as os_mouse
ImportError: No module named winmouse

import error Ubuntu 16.04

Importing the package doesn't work on my machine (Ubuntu 16.04):

Traceback (most recent call last):
  File "/home/canyon/git/keyboard_fork/test.py", line 1, in <module>
    import keyboard
  File "/home/canyon/git/keyboard_fork/keyboard/__init__.py", line 1, in <module>
    from .keyboard import *
  File "/home/canyon/git/keyboard_fork/keyboard/keyboard.py", line 8, in <module>
    from. import nixkeyboard as os_keyboard
  File "/home/canyon/git/keyboard_fork/keyboard/nixkeyboard.py", line 49, in <module>
    assert is_keypad_regular == is_keypad_shifted
AssertionError

The assertion fails at keycode 55. This is the relevant output of dumpkeys --keys-only:

...
keycode  55 = KP_Multiply     
    altgr   keycode  55 = Hex_C           
    shift   alt keycode  55 = Hex_C           
    altgr   shiftl  keycode  55 = Hex_C           
    shift   alt shiftl  keycode  55 = Hex_C           
    altgr   shiftr  keycode  55 = Hex_C           
    shift   alt shiftr  keycode  55 = Hex_C           
    altgr   shiftl  shiftr  keycode  55 = Hex_C           
    shift   alt shiftl  shiftr  keycode  55 = Hex_C           
    altgr   ctrll   keycode  55 = Hex_C           
    shift   alt ctrll   keycode  55 = Hex_C           
    altgr   shiftl  ctrll   keycode  55 = Hex_C           
    shift   alt shiftl  ctrll   keycode  55 = Hex_C           
    altgr   shiftr  ctrll   keycode  55 = Hex_C           
    shift   alt shiftr  ctrll   keycode  55 = Hex_C           
    altgr   shiftl  shiftr  ctrll   keycode  55 = Hex_C           
    shift   alt shiftl  shiftr  ctrll   keycode  55 = Hex_C  
...

I'm not sure if this could be causing the issue, but I'm using the German keyboard layout.

EDIT: the import works fine if comment the assertion line.

Key mapping error on non-English Windows

Using Python2.7(32bits) on W10(64bits).

The following is ok :
keyboard.press('s')

The following raises an exception :
keyboard.press('shift+s')

File "Z:\Eclipse\GamepadToKey\src\key_manager.py", line 25, in joy_set_button
keyboard.press(buttons_tab[button])
File "Z:\Eclipse\GamepadToKey\src\keyboard_init
.py", line 509, in press
send(combination, True, False)
File "Z:\Eclipse\GamepadToKey\src\keyboard_init_.py", line 501, in send
os_keyboard.press(to_scan_code(key))
File "Z:\Eclipse\GamepadToKey\src\keyboard_init
.py", line 479, in to_scan_code
scan_code, modifiers = _os_keyboard.map_char(_normalize_name(key))
File "Z:\Eclipse\GamepadToKey\src\keyboard_winkeyboard.py", line 244, in map_char
raise ValueError('Character {} is not mapped to any known key.'.format(repr(character)))
ValueError: Character 'shift' is not mapped to any known key.

Bug or Windows limitation ?

Alt keys aren't detected properly

As mentioned in a thread about a different issue:

When I run this program:

import keyboard
def info(event):
    print (event.name + ", " + str(event.scan_code) + ", " + event.event_type)
keyboard.hook(info)
keyboard.wait("esc")

and press left alt, I see "left alt, 56, down" as expected. When I release left alt, I see
left alt, 56, up
left alt, 56, down
left alt, 56, up

When I press and release right alt, I see:
left alt, 56, down
left alt, 56, up

I went looking for someplace else to test my keyboard events, and found https://w3c.github.io/uievents/tools/key-event-viewer.html
When I press and release left alt and then right alt in this tool, it looks like this:
http://i.imgur.com/FNNKpZn.png
It's not showing either problem.

I was slightly surprised that it was reporting my numlock status in this other tool. I tried turning off numlock to see if that made any difference to my "keyboard" problem. It didn't.

Windows 8.1
Tested on Python 2.7.13 and 3.6.0
keyboard 0.9.12

Better handling of dead keys

Right now the library doesn't care about dead keys at all. In Linux their status is known, but quickly stripped and ignored. In Windows there's no mention.

This may cause problems when trying to write text, because the library will try to use those keys as regular keys and the output will be jumbled.

May not be easy to implement on Windows.

An event.is_dead attribute would be nice too.

PS: this still better than some other libraries that simply break dead keys while they are running... Looking at you, pyHook.

No way to catch exceptions?

I'm trying to register a global hotkey, and if that fails, ask the user if they want to abort or continue regardless. However, the add_hotkey function doesn't throw an exception. Instead, an exception is thrown in a different thread.

Example:

import keyboard

try:
    keyboard.add_hotkey('ctrl+select', print, args=('foo',))
except:
    print('ERROR')
else:
    print('SUCCESS')

Output:

SUCCESS
Exception in thread Thread-1:
Traceback (most recent call last):
  File "/usr/lib64/python3.5/threading.py", line 914, in _bootstrap_inner
    self.run()
  File "/usr/lib64/python3.5/threading.py", line 862, in run
    self._target(*self._args, **self._kwargs)
  File "/usr/lib/python3.5/site-packages/keyboard/__init__.py", line 114, in listen
    _os_keyboard.listen(self.queue)
  File "/usr/lib/python3.5/site-packages/keyboard/_nixkeyboard.py", line 111, in listen
    build_device()
  File "/usr/lib/python3.5/site-packages/keyboard/_nixkeyboard.py", line 105, in build_device
    ensure_root()
  File "/usr/lib/python3.5/site-packages/keyboard/_nixcommon.py", line 163, in ensure_root
    raise ImportError('You must be root to use this library on linux.')
ImportError: You must be root to use this library on linux.

This behaviour is undesirable for obvious reasons, and there doesn't seem to be a workaround.

xauth warning and not registering keys on Linux

I'm running my program with sudo

Initailly I've gotten such result:

FileNotFoundError: [Errno 2] No such file or directory: '/root/.Xauthority'

then after creating empty .Xauthority file for root

Xlib.xauth: warning, no xauthority details available

Callbacks I've added arent executed when I press the keys.
Clearly some description of the issue is missing in the readme.

And here's how I'm using the llibrary:
https://github.com/mibli/i3-pyswitch/blob/feature/daemon/src/i3switch/input.py

Allow `press('keypad5')`

Currently it's possible to distinguish the side of the received events, but not generate events for specific sides. This should be fixed.

Linux problems on basic example

Hi, me again :-)
Got me a Linux laptop and trying to really use the lib on it, because of course, no AutoHotKey...
Unfortunately I can't get it to run a two-line test example (import keyboard, define one abbreviation).
With Python 2.7 it bombs:

Exception in thread Thread-1:
Traceback (most recent call last):
  File "/usr/lib/python2.7/threading.py", line 801, in __bootstrap_inner
    self.run()
  File "/usr/lib/python2.7/threading.py", line 754, in run
    self.__target(*self.__args, **self.__kwargs)
  File "/home/fpp/python/PyHotKey/keyboard/__init__.py", line 114, in listen
    _os_keyboard.listen(self.queue)
  File "/home/fpp/python/PyHotKey/keyboard/_nixkeyboard.py", line 111, in listen
    build_device()
  File "/home/fpp/python/PyHotKey/keyboard/_nixkeyboard.py", line 106, in build_device
    device = aggregate_devices('kbd')
  File "/home/fpp/python/PyHotKey/keyboard/_nixcommon.py", line 145, in aggregate_devices
    uinput = make_uinput()
  File "/home/fpp/python/PyHotKey/keyboard/_nixcommon.py", line 48, in make_uinput
    uinput.read = lambda n: Queue().get()
AttributeError: 'file' object attribute 'read' is read-only

With Python3.5 there is no exception but no abbreviation expanding either...

This is on XUbuntu 16.04, running the script as root in xterm and testing in Mousepad.
Anything I'm doing wrong ?...

Number pad keys have same scan code as some other keys

I have noticed that the number pad keys have the same scan code as other keys. This is a problem because I cannot distinguish the difference between pressing arrow down and pressing "2." I also do not seem to be able to distinguish when number lock is pressed.

Adding a key with a localized name on Windows makes all other keys raise errors.

  • OS: 64-bit Windows 10
  • System locale: Swedish
  • keyboard version: 0.9.13

This simple line of code causes big problems on my system:

keyboard.add_hotkey('up', lambda: print("Registered."))

("up" may be substituted with "up arrow", "down", "down arrow", "left", "left arrow", "right", or "right arrow" to get the same result).

After running this, pressing the specified arrow key works as expected and calls the callback. Pressing literally any other key on the keyboard, however, raises an error with the following traceback:

Traceback (most recent call last):
  File "C:\Python36-32\lib\site-packages\keyboard\_generic.py", line 23, in invoke_handlers
    if handler(event):
  File "C:\Python36-32\lib\site-packages\keyboard\__init__.py", line 296, in handler
    unexpected = not any(matches(event, part) for part in steps[state.step])
  File "C:\Python36-32\lib\site-packages\keyboard\__init__.py", line 296, in <genexpr>
    unexpected = not any(matches(event, part) for part in steps[state.step])
  File "C:\Python36-32\lib\site-packages\keyboard\__init__.py", line 152, in matches
    return matched_name or _os_keyboard.map_char(normalized)[0] == event.scan_code
  File "C:\Python36-32\lib\site-packages\keyboard\_winkeyboard.py", line 447, in map_char
    raise ValueError('Key name {} is not mapped to any known key.'.format(repr(name)))
ValueError: Key name 'up' is not mapped to any known key.

On further inspection, this seems to be because the key names in to_scan_code are localized (wtf, Windows?). It seems to be issue #12 coming back to bite you again! I suppose you fixed the ability to add keys with localized key names - just not without every other key breaking. 😉

Scan codes not set

Certain applications with low-level functionality (like Citrix) check the scan code for keyboard events as well as the virtual key code. If the scan code isn't set, they will miss certain keys like the arrow keys (though other keys will work fine).

I'm running into this issue with the current release of keyboard. I'll submit a pull request in a bit.

Not all keys are getting recognize

I'm using the keyboard.hook function and certain keys like "ñ", "ç", "´", " ' ", "¡" and "º" are not getting recognize. Also when you input something like shift+. it recognizes something like left shift and . instead of : . Is there a way to change that?
Great job on the code btw, pyhook is a mess.

Should it be this awkward to have a user define a hotkey?

I'm writing an application where the user can define their own global hotkeys. The interface for this is: they click a button, it says "press the key you want", they press it.

This was slightly more complicated to accomplish using "keyboard" than I expected it to be. Here is some simplified example code:

import keyboard
my_key = None

def record_key(event):
    global my_key
    if event.event_type == keyboard.KEY_DOWN:
        my_key = event.scan_code

print "select a hotkey"
callback = keyboard.hook(record_key)
while my_key is None:
    pass
keyboard.unhook(callback)
print "selected key code: " + str(my_key)

def fn():
    print "you pressed it"
keyboard.hook_key(int(my_key), keydown_callback=fn)

while True:
    pass

Am I missing something that makes this simpler? I expected to find something like, say, "keyboard.read_key()" that blocks until they press a key and returns what key they pressed.

I also found it surprising that if I don't cast my_key to int on that third-to-last line, I receive an error like

Traceback (most recent call last):
  File "C:\Python27\lib\site-packages\keyboard\_generic.py", line 23, in invoke_handlers
    if handler(event):
  File "C:\Python27\lib\site-packages\keyboard\__init__.py", line 350, in handler
    if not matches(event, key):
  File "C:\Python27\lib\site-packages\keyboard\__init__.py", line 139, in matches
    normalized = _normalize_name(name)
  File "C:\Python27\lib\site-packages\keyboard\_keyboard_event.py", line 215, in normalize_name
    raise ValueError('Can only normalize string names. Unexpected '+ repr(name))
ValueError: Can only normalize string names. Unexpected 30L

(30L is what it says if I press 'a', since its scancode is 30)
Shouldn't the library be able to receive a scancode back as the same kind of datatype it gave to me?

(I'm using the scancode and not the name because the name is reported as "unknown" for many some keys, and incorrectly for others. like my left ctrl and left alt both show as having "right" in their name instead of left)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.