Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to obtain the keycodes in Python

I have to know what key is pressed, but not need the code of the Character, i want to know when someone press the 'A' key even if the key obtained is 'a' or 'A', and so with all other keys.

I can't use PyGame or any other library (including Tkinter). Only Python Standard Library. And this have to be done in a terminal, not a graphical interface.

NOT NEED THE CHARACTER CODE. I NEED TO KNOW THE KEY CODE.

Ex:

ord('a') != ord('A')                      # 97 != 65
someFunction('a') == someFunction('A')    # a_code == A_code
like image 603
Lucas Gabriel Sánchez Avatar asked Feb 22 '09 20:02

Lucas Gabriel Sánchez


4 Answers

See tty standard module. It allows switching from default line-oriented (cooked) mode into char-oriented (cbreak) mode with tty.setcbreak(sys.stdin). Reading single char from sys.stdin will result into next pressed keyboard key (if it generates code):

import sys
import tty
tty.setcbreak(sys.stdin)
while True:
    print ord(sys.stdin.read(1))

Note: solution is Unix (including Linux) only.

Edit: On Windows try msvcrt.getche()/getwche(). /me has nowhere to try...


Edit 2: Utilize win32 low-level console API via ctypes.windll (see example at SO) with ReadConsoleInput function. You should filter out keypresses - e.EventType==KEY_EVENT and look for e.Event.KeyEvent.wVirtualKeyCode value. Example of application (not in Python, just to get an idea) can be found at http://www.benryves.com/tutorials/?t=winconsole&c=4.

like image 162
myroslav Avatar answered Sep 21 '22 06:09

myroslav


This is a topic that I have been grappling with recently. Another thing to check here is if you are getting correct values in different keyboard layouts. For example it doesn't look like pygame reports number key codes correctly when you switch into a French - PC layout. My suggestion is to use wxPython. It exposes the platform specific key codes in the RawKeyCode property. Here is a code sample which demonstrates that:

import logging as log
import wx

class MainWindow(wx.Frame):
    def __init__(self, parent, title):
        wx.Frame.__init__(self, parent, title=title, size=(200,100))

        self.panel = wx.Panel(self, wx.ID_ANY)
        self.panel.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown)
        self.panel.Bind(wx.EVT_KEY_UP, self.OnKeyDown)
        self.panel.Bind(wx.EVT_CHAR, self.OnKeyDown)
        self.panel.SetFocus()
        self.Show(True)

    def OnKeyDown(self, event=None):
        line_txt = '---------------------'
        print(line_txt)
        for var in ['RawKeyCode', 'KeyCode', 'UnicodeKey']:
            print(var, getattr(event, var))
            if var == 'UnicodeKey':
                print('char', chr(getattr(event, var)))
        print(line_txt)


if __name__ == "__main__":
    app = wx.App(False)
    gui = MainWindow(None, "test")
    app.MainLoop()

For example when I hit the fn key on my mac (a mac-only key) I see this logged:

---------------------
RawKeyCode 63
KeyCode 0
UnicodeKey 0
char 
---------------------

Which is consistent with the platform specific key codes here.

like image 20
spacether Avatar answered Sep 23 '22 06:09

spacether


Take a look at pynput module in Python. It also has a nice tutorial using which you can easily create keyboard listeners for your code.

The official example for listeners is:

from pynput.keyboard import Key, Listener

def on_press(key):
    print('{0} pressed'.format(
        key))

def on_release(key):
    print('{0} release'.format(
        key))
    if key == Key.esc:
        # Stop listener
        return False

# Collect events until released
with Listener(on_press=on_press,
              on_release=on_release) as listener:
    listener.join()

Hope this helps.

like image 25
Ankit Bindal Avatar answered Sep 19 '22 06:09

Ankit Bindal


Depending on what you are trying to accomplish, perhaps using a library such as pygame would do what you want. Pygame contains more advanced keypress handling than is normally available with Python's standard libraries.

like image 32
Greg Hewgill Avatar answered Sep 20 '22 06:09

Greg Hewgill