Coder Social home page Coder Social logo

boppreh / keyboard Goto Github PK

View Code? Open in Web Editor NEW
3.7K 79.0 432.0 1.37 MB

Hook and simulate global keyboard events on Windows and Linux.

License: MIT License

Python 99.66% Makefile 0.34%
python keyboard-events keyboard-hooks keyboard-state hotkey register-hotkey scancode callback

keyboard's People

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

keyboard's Issues

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

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.

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.

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

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?

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 ?...

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.

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.

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.

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.

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

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)

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.

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.

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?

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!

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

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.

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

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.

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.

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.

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.

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.

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. :(

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.

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.

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?

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)}

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. 😉

"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?)

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

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.

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

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 ?

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?

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?

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.

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'))

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

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

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

module import error

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

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.