如何在Python中获取密钥代码

时间:2009-02-22 20:01:22

标签: python input keycode

我必须知道按下了什么键,但不需要字符的代码,我想知道有人按下'A'键,即使获得的键是'a'或'A',所以所有其他钥匙。

我不能使用PyGame或任何其他库(包括Tkinter)。只有Python标准库。这必须在终端中完成,而不是图形界面。

不需要字符代码。我需要知道关键代码。

例如:

ord('a') != ord('A')                      # 97 != 65
someFunction('a') == someFunction('A')    # a_code == A_code

8 个答案:

答案 0 :(得分:20)

请参阅tty标准模块。它允许使用tty.setcbreak(sys.stdin)从默认的面向行(煮熟)模式切换到面向字符的(cbreak)模式。从sys.stdin中读取单个字符将导致下一个按下的键盘键(如果它生成代码):

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

注意:解决方案仅限于Unix(包括Linux)。

修改:在Windows上尝试msvcrt.getche() / getwche()。 /我无处可试......


编辑2:通过ctypes.windll使用win32低级控制台API(请参阅example at SO)并使用ReadConsoleInput功能。您应该过滤掉按键 - e.EventType==KEY_EVENT并查找e.Event.KeyEvent.wVirtualKeyCode值。可以在http://www.benryves.com/tutorials/?t=winconsole&c=4找到应用程序示例(不是在Python中,只是为了获得一个想法)。

答案 1 :(得分:9)

根据您要完成的任务,可能使用pygame之类的库可以满足您的需求。 Pygame包含比Python标准库通常提供的更高级的按键处理。

答案 2 :(得分:3)

您可能必须使用Tkinter,这是'标准'Python gui,并且已经包含在python中多年。

由于数据传入和传出命令行进程的方式,命令行解决方案可能不可用。 GUI程序(某些风格或其他)都通过(可能是库包装的)事件流接收用户输入。每个活动都将记录活动的详细信息。对于击键事件,记录可能包含某些编码中的任何键码,修饰键位域或文本字符。哪些字段及其命名方式取决于您调用的事件库。

命令行程序通过字符流接收用户输入。无法捕获较低级别的数据。正如myroslav在帖子中解释的那样,tty可以处于熟或未烹饪模式,唯一的区别是在熟模式下终端将为您处理(某些)控制字符,如删除和输入,以便进程接收输入行,而不是每次1个字符。

处理低于此要求的任何内容(需要依赖于OS)系统调用或在/ dev中打开字符设备。 Python的标准库没有为此提供标准工具。

答案 3 :(得分:0)

如果您只需要在Windows中工作,则应尝试msvcrt

答案 4 :(得分:0)

显而易见的答案:

someFunction = string.upper

ord('a') != ord('A')                      # 97 != 65
someFunction('a') == someFunction('A')    # a_code == A_code

或其他(关键)词:

char_from_user = getch().upper() # read a char converting to uppercase
if char == 'Q':
    # quit
    exit = True # or something
elif char in ['A', 'K']:
    do_something()

等...

这是getch函数的一个实现,它可以在Windows和Linux平台上运行,based on this recipe

class _Getch(object):
    """Gets a single character from standard input.  
       Does not echo to the screen."""
    def __init__(self):
        try:
            self.impl = _GetchWindows()
        except ImportError:
            self.impl = _GetchUnix()

    def __call__(self): 
        return self.impl()

class _GetchUnix(object):
    def __init__(self):
        import tty, sys

    def __call__(self):
        import sys, tty, termios
        fd = sys.stdin.fileno()
        old_settings = termios.tcgetattr(fd)
        try:
            tty.setraw(sys.stdin.fileno())
            ch = sys.stdin.read(1)
        finally:
            termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
        return ch


class _GetchWindows(object):
    def __init__(self):
        import msvcrt

    def __call__(self):
        import msvcrt
        return msvcrt.getch()


getch = _Getch()

答案 5 :(得分:0)

此函数将返回大写字符的代码:

def upCcode( ch ):
    if(len(ch) == 1):
        return ord(ch.upper())

这是小写字符代码:

def lowCcode( ch ):
        if(len(ch) == 1):
            return ord(ch.lower())

这种方式更容易,您不需要导入外部库。

您需要选择两种方法中的一种作为' someFunction'你在问题中描述过。这是一个例子:

输出:

# when using upCode():
>> upCcode('a')
65

>> upCcode('A')
65

# when using lowCode():
>> lowCcode('a')
97

>> lowCcode('A')
97

答案 6 :(得分:0)

在Python中查看pynput模块。它还有一个很好的tutorial使用,你可以轻松地为你的代码创建键盘监听器。

听众的官方例子是:

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

希望这有帮助。

答案 7 :(得分:0)

这是我最近一直在努力的话题。 这里要检查的另一件事是,您是否在不同的键盘布局中获得正确的值。例如,当您切换到法语-PC布局时,pygame看起来好像无法正确报告数字键代码。我的建议是使用wxPython。它在RawKeyCode属性中公开特定于平台的键代码。 这是一个代码示例,演示了这一点:

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

例如,当我在Mac上按fn键(仅限Mac的键)时,会看到以下记录:

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

platform specific key codes here一致。