用于读取按键的Python方法?

时间:2012-08-29 10:33:09

标签: python windows key keydown getch

我是Python的新手,我只是在Python中创建了游戏和菜单。 问题是,使用(raw_)input()要求我在每次按键后按Enter键,我想按下向下箭头将立即选择下一个菜单项,或者在游戏中向下移动。目前,它需要我喜欢类型" down"然后按回车键。我也做了很多研究,但我不想下载大型模块(例如pygame)来实现单个keyDown()方法。那么有什么更简单的方法,我无法找到吗?

修改 刚刚发现msvcrt.getch()可以解决问题。它不是keyDown(),但它有效。但是,我也不确定如何使用它,这看起来很奇怪,这里有什么帮助吗?这就是我现在所得到的:

from msvcrt import getch
while True:
    key = getch()
    print(key)

然而,它一直给我所有这些无意义的字节,例如,向下箭头是这样的:

b'\xe0'
b'P'

我不知道如何使用它们,我已经尝试与chr()进行比较,甚至使用ord(),但无法进行任何比较。我试图做的基本上是这样的:

from msvcrt import getch
while True:
    key = getch()
    if key == escape:
        break
    elif key == downarrow:
        movedown()
    elif key == 'a':
        ...

等等......有什么帮助吗?

6 个答案:

答案 0 :(得分:56)

通过自己测试所有内容来计算出来。 找不到任何关于它的话题,所以我将在这里留下解决方案。这可能不是唯一的,甚至是最好的解决方案,但它适用于我的目的(在getch的限制范围内)并且总比没有好。

注意:正确识别所有键和实际按键的keyDown()仍然有价值。

解决方案:使用ord() - 函数首先将getch()转换为整数(我猜它们是虚拟键码,但不太确定)工作正常,然后将结果与表示所需密钥的实际数字进行比较。此外,如果我需要,我可以在返回的数字周围添加额外的chr(),以便将其转换为字符。但是,我主要使用向下箭头,esc等,所以将它们转换为角色将是愚蠢的。这是最终的代码:

from msvcrt import getch
while True:
    key = ord(getch())
    if key == 27: #ESC
        break
    elif key == 13: #Enter
        select()
    elif key == 224: #Special keys (arrows, f keys, ins, del, etc.)
        key = ord(getch())
        if key == 80: #Down arrow
            moveDown()
        elif key == 72: #Up arrow
            moveUp()

此外,如果其他人需要,您可以轻松找到谷歌的密码,或使用python,只需按键:

from msvcrt import getch
while True:
    print(ord(getch()))

答案 1 :(得分:8)

请参阅MSDN getch文档。具体做法是:

  

_getch和_getwch函数从控制台读取单个字符而不回显字符。这些函数都不能用于读取CTRL + C.读取功能键或箭头键时,每个功能必须调用两次;第一个调用返回0或0xE0,第二个调用返回实际的键代码。

Python函数返回一个字符。您可以使用ord()来获取可以测试的整数值,例如keycode = ord(msvcrt.getch())

因此,如果您读取0x00或0xE0,请再次读取它以获取箭头或功能键的键代码。从实验来看,0x00在F1-F10(0x3B-0x44)之前,0xE0在箭头键和Ins / Del / Home / End / PageUp / PageDown之前。

答案 2 :(得分:1)

AppDelegate.m

答案 3 :(得分:1)

我真的不想发布此评论,因为我需要评论所有答案和原始问题。

所有答案似乎都依赖于MSVCRT Microsoft Visual C Runtime。 如果您想避免这种依赖性:

  

如果需要跨平台支持,请在此处使用库:

     

https://pypi.org/project/getkey/#files

     

https://github.com/kcsaff/getkey

     

可以提供更优雅的解决方案。

代码示例:

from getkey import getkey, keys
key = getkey()
if key == keys.UP:
  ...  # Handle the UP key
elif key == keys.DOWN:
  ...  # Handle the DOWN key
elif key == 'a':
  ...  # Handle the `a` key
elif key == 'Y':
  ...  # Handle `shift-y`
else:
  # Handle other text characters
  buffer += key
  print(buffer)

答案 4 :(得分:1)

现在真的很晚了,但我制作了一个适用于 Windows、Mac 和 Linux 的快速脚本,只需使用每个命令行即可:

import os, platform

def close():
    if platform.system() == "Windows":
        print("Press any key to exit . . .")
        os.system("pause>nul")
        exit()
    
    elif platform.system() == "Linux":
        os.system("read -n1 -r -p \"Press any key to exit . . .\" key")
        exit()
    
    elif platform.system() == "Darwin":
        print("Press any key to exit . . .")
        os.system("read -n 1 -s -p \"\"")
        exit()
    
    else:
        exit()

它只使用内置函数,并且应该适用于所有三个(虽然我只测试了 Windows 和 Linux...)。

答案 5 :(得分:0)

我也在努力实现这一目标。从上面的代码中,我了解到您可以多次调用getch()函数,以使两个字节均从该函数获取。因此,如果您只是想与字节对象一起使用,则不需要ord()函数。

while True :
    if m.kbhit() :
        k = m.getch()
        if b'\r' == k :
            break
        elif k == b'\x08'or k == b'\x1b':
            # b'\x08' => BACKSPACE
            # b'\x1b' => ESC
            pass
        elif k == b'\xe0' or k == b'\x00':
            k = m.getch()
            if k in [b'H',b'M',b'K',b'P',b'S',b'\x08']:
                # b'H' => UP ARROW
                # b'M' => RIGHT ARROW
                # b'K' => LEFT ARROW
                # b'P' => DOWN ARROW
                # b'S' => DELETE
                pass
            else:
                print(k.decode(),end='')
        else:
            print(k.decode(),end='')

此代码将可以打印任何键,直到在CMD或IDE中按Enter键为止 (我正在使用VS CODE) 您可以根据需要在if内部自定义特定键