Python跨平台监听按键操作?

21
我需要在Python终端程序中监听某些按键,而不使用raw_input来暂停执行。我见过一些Windows特定的按键监听方法,也见过人们使用像tkinter和pygame这样的大模块,但我想避免这些方法。是否有一个跨平台的轻量级模块可以做到这一点(至少在Ubuntu、Windows、Mac上)?或者是否有一种方法只使用tkinter、pygame等事件系统?如果没有,我应该如何解决这个问题?我的第一个想法是将标准输入重定向到另一个进程,并不断检查它是否包含我的事件键之一。
4个回答

8
我不知道有哪些跨平台的轻量级模块可以监听按键。但是,如果你想实现一些简单的东西,以下是一个建议:
查看Python FAQ中有关在每次只获取一个按键的问题。你可以尝试从sys.stdinthreading进行阻塞读取。但这可能只适用于Unix系统。在Windows上,你可以使用msvcrt.kbhit
将Python FAQ中的按键示例和msvcrt模块组合起来,最终的kbhit函数将如下所示:
try:
    from msvcrt import kbhit
except ImportError:
    import termios, fcntl, sys, os
    def kbhit():
        fd = sys.stdin.fileno()
        oldterm = termios.tcgetattr(fd)
        newattr = termios.tcgetattr(fd)
        newattr[3] = newattr[3] & ~termios.ICANON & ~termios.ECHO
        termios.tcsetattr(fd, termios.TCSANOW, newattr)
        oldflags = fcntl.fcntl(fd, fcntl.F_GETFL)
        fcntl.fcntl(fd, fcntl.F_SETFL, oldflags | os.O_NONBLOCK)
        try:
            while True:
                try:
                    c = sys.stdin.read(1)
                    return True
                except IOError:
                    return False
        finally:
            termios.tcsetattr(fd, termios.TCSAFLUSH, oldterm)
            fcntl.fcntl(fd, fcntl.F_SETFL, oldflags)

1
def kbhit(): ... return sys.stdin.read(1) - seriyPS
+1 在您的帮助下,我成功地完成了我需要处理的问题。谢谢。 - rennat
2
-1 这里 不含有类似于 msvcrt 模块的 kbhit() 函数,它仅测试按键是否被按下。这是因为它基于 Python FAQ 中获取单个按键的代码。您的修改在有字符输入时获取并丢弃读取的字符,因此该字符将丢失。 - martineau
导入kbhit后,您要做什么?如何使用它? - CMCDragonkai
EI Capitan 10.11.3(15D21),我遇到了这个错误:termios.error: (25, 'Inappropriate ioctl for device')。 - Zhang LongQI

6
简短回答:不行。键盘按键是与系统相关的,它们是中断驱动的。这是大多数现代操作系统中内置的基本功能之一。它们有不同的哲学,无法以通用方式统一,否则会失去功能。 您可以尝试使用以下内容: termios = unix、posix 风格的文件描述符驱动 curses = 门户终端风格处理(这是一种特定的基于控制台的范例,而不是通用的) Python包装了某些可能来自键盘的输入类:例如,sys.stdin 用于控制台输入。 但是,试图获得通用键盘输入是一个非常普遍的问题,固有地依赖于平台。

0
你可以使用 Python 模块 plataform,获取当前操作系统信息,然后针对每个平台制定解决方案:
import platform
platform.platform()
'Linux-3.3.0-8.fc16.x86_64-x86_64-with-fedora-16-Verne'

-1

以下是在Windows上如何实现的方法:

"""

    Display series of numbers in infinite loop
    Listen to key "s" to stop
    Only works on Windows because listening to keys
    is platform dependent

"""

# msvcrt is a windows specific native module
import msvcrt
import time

# asks whether a key has been acquired
def kbfunc():
    #this is boolean for whether the keyboard has bene hit
    x = msvcrt.kbhit()
    if x:
        #getch acquires the character encoded in binary ASCII
        ret = msvcrt.getch()
    else:
        ret = False
    return ret

#begin the counter
number = 1

#infinite loop
while True:

    #acquire the keyboard hit if exists
    x = kbfunc() 

    #if we got a keyboard hit
    if x != False and x.decode() == 's':
        #we got the key!
        #because x is a binary, we need to decode to string
        #use the decode() which is part of the binary object
        #by default, decodes via utf8
        #concatenation auto adds a space in between
        print ("STOPPING, KEY:", x.decode())
        #break loop
        break
    else:
        #prints the number
        print (number)
        #increment, there's no ++ in python
        number += 1
        #wait half a second
        time.sleep(0.5)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接