Python跨平台监听按键?

时间:2011-02-18 16:48:20

标签: python keyboard-events

我需要在python终端程序中监听某些按键,而不会暂停执行raw_input。我已经看到人们使用一些窗口特定的方式来听取击键,我看到人们使用像tkinter和pygame这样的大模块,我想避免使用。

是否有一个轻量级模块可以实现这个跨平台(至少是ubuntu,windows,mac)?或者有没有办法只使用来自tkinter,pygame等的事件系统......?

如果没有,我应该怎样处理这个问题?我的第一个想法是将stdin重定向到另一个进程并继续检查它是否包含我的一个事件键。


修改

感谢@unutbu花时间将这个问题标记为3年,并成功回答了另一个问题的副本,其答案不适用于此问题,因为我特别询问了非阻塞解决方案。

3 个答案:

答案 0 :(得分:7)

我不知道任何侦听按键的跨平台轻量级模块。但是如果你想要实现一些简单的事情,这里有一个建议:

在Python常见问题解答中查看getting a single keypress at a time上的这个问题。您可以尝试阻止来自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 :(得分:6)

简答:不 Keress是系统依赖的。它们是中断驱动的。它们是大多数现代操作系统中内置的基本内容之一。他们有不同的理念,在不失去功能的情况下无法以通用方式统一。

你可以尝试 - termios = unix,posix风格的文件描述符驱动

curses =门户网站终端式处理(这是一种特定的基于控制台的范例,不是通用的)

Python包装可能来自键盘的某些输入类:例如,sys.stdin用于控制台inupt。

但是试图获得通用键盘输入是一个非常普遍的问题,它本身就依赖于平台。

答案 2 :(得分:0)

以下是在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)