在python中检测按键?

lob*_*buo 64 python keypress detect python-2.7

我在python中制作秒表类型程序,我想知道如何检测是否按下了一个键(例如p表示暂停,s表示停止),我不希望它像raw_input那样等待用户在继续执行之前的输入.任何人都知道如何在while循环中执行此操作?

另外,我想制作这个跨平台,但如果不可能,那么我的主要开发目标是linux

小智 41

Python有一个具有许多功能的键盘模块.安装它,也许使用此命令:

pip3 install keyboard
Run Code Online (Sandbox Code Playgroud)

然后在代码中使用它:

import keyboard  # using module keyboard
while True:  # making a loop
    try:  # used try so that if user pressed other than the given key error will not be shown
        if keyboard.is_pressed('q'):  # if key 'q' is pressed 
            print('You Pressed A Key!')
            break  # finishing the loop
    except:
        break  # if user pressed a key other than the given key the loop will break
Run Code Online (Sandbox Code Playgroud)

  • `keyboard`显然需要linux中的root:/ (36认同)
  • 我不确定是否适用于 linux,但它对我来说适用于 Windows。 (6认同)
  • 我不明白为什么try:except:会有用。 (6认同)
  • 这个解决方案似乎使用了大量的CPU。我一个人这么认为吗? (4认同)
  • 我尝试了这个解决方案,但花了一段时间才意识到它会在您的应用程序在终端中运行并且未处于焦点时触发。对于很多应用程序来说可能没问题,但对我来说却是一种破坏,因为我正在运行多个进程。 (2认同)
  • “为避免依赖X,Linux部件读取原始设备文件(/ dev / input / input *),但这需要root。” (2认同)

Mit*_*rek 24

对于那些在窗户上并且正在努力寻找工作答案的人来说,我的是: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()
Run Code Online (Sandbox Code Playgroud)

上面的功能将打印您按下的任何键,并在释放'esc'键时启动操作.键盘文档在这里用于更多变化的用法.

  • 在Linux中也可以使用,谢谢! (5认同)
  • @ nimig18 ...并且不需要root :) (2认同)
  • 此解决方案存在一个问题(不确定替代方案):不必在控制台窗口内按下该键即可使其生效。想象一下,有一个脚本在按下 ESC 之前执行某些工作,但随后您在另一个程序中按下它。 (2认同)
  • 应该是公认的答案,因为它在 Linux 和 Windows 中都适用 (2认同)

Abc*_*Xyz 19

OP提到raw_input - 这意味着他想要cli解决方案.Linux:curses就是你想要的(windows PDCurses).Curses,是一个用于cli软件的图形API,您可以实现的不仅仅是检测关键事件.

此代码将检测键,直到按下新行.

import curses
import os

def main(win):
    win.nodelay(True)
    key=""
    win.clear()                
    win.addstr("Detected key:")
    while 1:          
        try:                 
           key = win.getkey()         
           win.clear()                
           win.addstr("Detected key:")
           win.addstr(str(key)) 
           if key == os.linesep:
              break           
        except Exception as e:
           # No input   
           pass         

curses.wrapper(main)
Run Code Online (Sandbox Code Playgroud)

  • 需要添加`import os`以便能够退出退出示例. (4认同)
  • 这真的很好。在遇到它之前必须一直寻找。看起来比使用“termios”等更干净...... (2认同)

J0A*_*NMM 18

neoDev 对问题本身的评论可能很容易被忽略,但它链接到此处任何答案中未提及的解决方案。

使用此解决方案无需导入keyboard

另一个问题复制的解决方案,全部归功于@neoDev。

这在 macOS Sierra 和 Python 2.7.10 和 3.6.3 上对我有用

import sys,tty,os,termios
def getkey():
    old_settings = termios.tcgetattr(sys.stdin)
    tty.setcbreak(sys.stdin.fileno())
    try:
        while True:
            b = os.read(sys.stdin.fileno(), 3).decode()
            if len(b) == 3:
                k = ord(b[2])
            else:
                k = ord(b)
            key_mapping = {
                127: 'backspace',
                10: 'return',
                32: 'space',
                9: 'tab',
                27: 'esc',
                65: 'up',
                66: 'down',
                67: 'right',
                68: 'left'
            }
            return key_mapping.get(k, chr(k))
    finally:
        termios.tcsetattr(sys.stdin, termios.TCSADRAIN, old_settings)
try:
    while True:
        k = getkey()
        if k == 'esc':
            quit()
        else:
            print(k)
except (KeyboardInterrupt, SystemExit):
    os.system('stty sane')
    print('stopping.')
Run Code Online (Sandbox Code Playgroud)


Ben*_*jie 11

对于Windows,您可以这样使用msvcrt:

   import msvcrt
   while True:
       if msvcrt.kbhit():
           key = msvcrt.getch()
           print(key)   # just to show the result
Run Code Online (Sandbox Code Playgroud)

  • msvcrt是一个仅限Windows的模块. (7认同)

Bla*_*der 7

使用keyboard模块可以做更多的事情。

以下是一些方法:


方法1:

使用功能read_key()

import keyboard

while True:
    if keyboard.read_key() == "p":
        print("You pressed p")
        break
Run Code Online (Sandbox Code Playgroud)

p按下该键将打破循环。


方法2:

使用功能wait

import keyboard

keyboard.wait("p")
print("You pressed p")
Run Code Online (Sandbox Code Playgroud)

它将等待您按下p并继续按下代码。


方法3:

使用功能on_press_key

import keyboard

keyboard.on_press_key("p", lambda _:print("You pressed p"))
Run Code Online (Sandbox Code Playgroud)

它需要一个回调函数。我_之所以使用,是因为键盘功能将键盘事件返回到该功能。

一旦执行,当按下键时它将运行该功能。您可以通过运行以下行来停止所有挂钩:

keyboard.unhook_all()
Run Code Online (Sandbox Code Playgroud)

方法4:

user8167727已经回答了这种方法,但是我不同意他们编写的代码。它将使用该函数,is_pressed但以另一种方式:

import keyboard

while True:
    if keyboard.is_pressed("p"):
        print("You pressed p")
        break
Run Code Online (Sandbox Code Playgroud)

p按下后将打破循环。


笔记:

  • keyboard 将从整个操作系统读取按键。
  • keyboard 在Linux上需要root

  • 使用键盘模块最大的缺点是它要求您以ROOT用户身份运行。这使模块在我的代码中成为僵尸。仅轮询是否已按下键并不需要root特权。我已经阅读了文档并了解了为什么该限制会在模块中退出,但是如果您只需要轮询一个键,那么请查看其他地方... (3认同)

A.J*_*pal 6

使用PyGame拥有一个窗口,然后您可以获取关键事件。

对于这封信p

import pygame, sys
import pygame.locals

pygame.init()
BLACK = (0,0,0)
WIDTH = 1280
HEIGHT = 1024
windowSurface = pygame.display.set_mode((WIDTH, HEIGHT), 0, 32)

windowSurface.fill(BLACK)

while True:
    for event in pygame.event.get():
        if event.key == pygame.K_p: # replace the 'p' to whatever key you wanted to be pressed
             pass #Do what you want to here
        if event.type == pygame.locals.QUIT:
             pygame.quit()
             sys.exit()
Run Code Online (Sandbox Code Playgroud)

  • 我无法运行上面的代码。我首先必须检查事件类型是 KEYUP 或 KEYDOWN 之一: if event.type in (pygame.KEYDOWN, pygame.KEYUP): print("Key: ", event.key) if(event.key == pygame .K_q): pygame.quit() (6认同)

小智 6

使用此代码查找按下了哪个键

from pynput import keyboard

def on_press(key):
    try:
        print('alphanumeric key {0} pressed'.format(
            key.char))
    except AttributeError:
        print('special key {0} pressed'.format(
            key))

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

# Collect events until released
with keyboard.Listener(
        on_press=on_press,
        on_release=on_release) as listener:
    listener.join()
Run Code Online (Sandbox Code Playgroud)

  • 这是 Linux 中的方法,因为键盘库需要 root。 (3认同)
  • 该解决方案将检测**所有**击键;还有那些发生在不同终端窗口中的情况。不幸的是,这严重限制了它可能的用例。 (2认同)

小智 6

即使通过 ssh 也可以工作的非 root 版本:sshkeyboard。安装pip install sshkeyboard

然后编写脚本,例如:

from sshkeyboard import listen_keyboard

def press(key):
    print(f"'{key}' pressed")

def release(key):
    print(f"'{key}' released")

listen_keyboard(
    on_press=press,
    on_release=release,
)
Run Code Online (Sandbox Code Playgroud)

它会打印:

'a' pressed
'a' released
Run Code Online (Sandbox Code Playgroud)

A按键被按下时。ESC键默认结束监听。

它比curses、tkinter 和getch 等需要更少的编码。而且它不像键盘模块那样需要 root 访问权限。


Fer*_*erd 5

我根据这篇文章制作了这种游戏(使用msvcr库和Python 3.7)。

以下是游戏的主要功能,即检测按下的按键:

import msvcrt

def _secret_key(self):
    # Get the key pressed by the user and check if he/she wins.

    bk = chr(10) + "-"*25 + chr(10)

    while True:
        print(bk + "Press any key(s)" + bk)
        #asks the user to type any key(s)

        kp = str(msvcrt.getch()).replace("b'", "").replace("'", "")
        # Store key's value.

        if r'\xe0' in kp:
            kp += str(msvcrt.getch()).replace("b'", "").replace("'", "")
            # Refactor the variable in case of multi press.

        if kp == r'\xe0\x8a':
            # If user pressed the secret key, the game ends.
            # \x8a is CTRL+F12, that's the secret key.

            print(bk + "CONGRATULATIONS YOU PRESSED THE SECRET KEYS!\a" + bk)
            print("Press any key to exit the game")
            msvcrt.getch()
            break
        else:
            print("    You pressed:'", kp + "', that's not the secret key(s)\n")
            if self.select_continue() == "n":
                if self.secondary_options():
                    self._main_menu()
                break
Run Code Online (Sandbox Code Playgroud)

如果您想要该程序的完整源代码,您可以查看它或从 GitHub下载

秘密按键是:

Ctrl+F12