如何在Python中获取键码

发布于 2024-07-13 14:43:37 字数 334 浏览 6 评论 0 原文

我必须知道按下了什么键,但不需要角色的代码,我想知道何时有人按下“A”键,即使获得的键是“a”或“A”,所有其他键也是如此。

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

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

前任:

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

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

生生不灭 2024-07-20 14:43:37

请参阅 tty 标准模块。 它允许使用 tty.setcbreak(sys.stdin)。 从 sys.stdin 读取单个字符将导致下一个按下的键盘键(如果它生成代码):

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

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

编辑:在 Windows 上尝试 msvcrt.getche()/getwche()。 /me 无处可尝试...


编辑 2:通过 ctypes.windll 利用 win32 低级控制台 API (参见示例) 使用 ReadConsoleInput 函数。 您应该过滤掉按键 - e.EventType==KEY_EVENT 并查找 e.Event.KeyEvent.wVirtualKeyCode 值。 应用程序示例(不是 Python,只是为了了解一下)可以在 找到http://www.benryves.com/tutorials/?t=winconsole&c=4

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.

半寸时光 2024-07-20 14:43:37

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

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.

忆沫 2024-07-20 14:43:37

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

官方给听众的例子是:

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

希望这有帮助。

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.

二智少女 2024-07-20 14:43:37

您可能必须使用 Tkinter,它是“标准”Python gui,并且已被包含在 python 中很多年了。

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

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

处理低于此值的任何内容都需要(取决于操作系统)系统调用或在 /dev 中打开字符设备。 Python 的标准库没有为此提供标准设施。

You probably will have to use Tkinter, which is the 'standard' Python gui, and has been included with python for many years.

A command-line solution is probably not available, because of the way data passes into and out of command-line processes. GUI programs (of some flavor or another) all recieve user-input through a (possibly library wrapped) event stream. Each event will be a record of the event's details. For keystroke events, the record will may contain any of a keycode, modifier key bitfield, or text character in some encoding. Which fields, and how they are named depends on the event library you are calling.

Command-line programs recieve user input through character-streams. There is no way to catch lower-level data. As myroslav explained in his post, tty's can be in cooked or uncooked mode, the only difference being that in cooked mode the terminal will process (some) control characters for you, like delete and enter so that the process receives lines of input, instead of 1 character at a time.

Processing anything lower than that requires (OS dependent) system calls or opening character devices in /dev. Python's standard library provides no standard facility for this.

梦在深巷 2024-07-20 14:43:37

这是我最近一直在思考的一个话题。
这里要检查的另一件事是您是否在不同的键盘布局中获得了正确的值。 例如,当您切换到法语 - 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 
---------------------

这与 此处为平台特定的关键代码

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.

兮子 2024-07-20 14:43:37

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

If you need to work in windows only you should try msvcrt.

朦胧时间 2024-07-20 14:43:37

显而易见的答案:

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 平台上工作, 基于此食谱

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

The obvious answer:

someFunction = string.upper

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

or, in other (key)words:

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

etc...

Here is a implementation of the getch function, that would work in both Windows and Linux platforms, 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()
樱桃奶球 2024-07-20 14:43:37

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

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

this function will return the code for the uppercase character:

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

and this is for the lowercase character code:

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

this way is far easier, and you won't need to import external libraries.

You will need to choose one of the two methods to be the 'someFunction' you described in your question. Here's an example:

OUTPUT:

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

>> upCcode('A')
65

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

>> lowCcode('A')
97
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文