Python跨平台监听按键?

发布于 2024-10-18 02:42:14 字数 386 浏览 0 评论 0原文

我需要在 python 终端程序中监听某些按键,而不用 raw_input 暂停执行。我见过人们使用一些特定于 Windows 的方式来监听击键,并且我见过人们使用像 tkinter 和 pygame 这样的大型模块,我想避免这些模块。

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

如果不是,我应该如何解决这个问题?我的第一个想法是将标准输入重定向到另一个进程,并继续检查它是否包含我的事件键之一。


编辑

感谢@unutbu 花时间标记这个已有 3 年历史的问题,并成功回答为另一个问题的重复,该问题的答案不适用于该问题,因为我专门询问了非阻塞解决方案。

I need to listen for certain keypresses in a python terminal program without pausing execution with raw_input. I've seen people use a few windows specific ways of listening for keystrokes and I've seen people use large modules like tkinter and pygame which I want to avoid.

Is there a lightweight module out there that does this cross platform (at least ubuntu, windows, mac)? or is there a way to use just the event system from tkinter, pygame, etc...?

If not, how should I approach tackling this? My first thought is to redirect stdin to another process and keep checking to see if it contains one of my event keys.


edit

Thank you @unutbu for taking the time to mark this question that is 3 years old and successfully answered as a duplicate of another question whose answers do not apply to this question because I specifically asked about a non-blocking solution.

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

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

发布评论

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

评论(4

治碍 2024-10-25 02:42:14

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

一次按下一个按键。您可以尝试一下阻止从 sys.stdin 和线程读取。但这可能只适用于 Unix。在 Windows 上,您可以使用 msvcrt.kbhit< /a>.

结合 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)

I don't know of any cross-platform lightweight module that listens for keypresses. But here's a suggestion in case you want to implement something simple:

Check out this question on getting a single keypress at a time in the Python FAQ. You could experiment a bit with blocking reads from sys.stdin and threading. But this may only work on Unix. On Windows, you can use msvcrt.kbhit.

Combining the keypress recipe from the Python FAQ and the msvcrt module, the resulting kbhit function would go like this:

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)
若沐 2024-10-25 02:42:14

简短回答:不
按键取决于系统。它们是中断驱动的。它们是大多数现代操作系统内置的基本功能之一。它们具有不同的理念,无法在不损失功能的情况下以通用方式统一。

你可以尝试-
termios = unix,posix 样式文件描述符驱动

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

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

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

Short answer: no
Keypresses are system-dependent. They are interrupt-driven. They one of the basic things built into most modern OSes. They have different philosophies that can't be unified in a generic way without losing functionality.

you might try-
termios = unix, posix-style file-descriptor driven

curses = portal terminal-style handling (which is a specific console-based paradigm not generic)

Python wraps certain classes of input that might come from the keyboard: e.g., sys.stdin for console inupt.

But trying to get universal keyboard input is a very general problem that's inherently platform-dependent.

浅忆流年 2024-10-25 02:42:14

您可以使用 python 模块 plataform 来获取当前操作系统,然后为每个平台制定解决方案:

import platform
platform.platform()
'Linux-3.3.0-8.fc16.x86_64-x86_64-with-fedora-16-Verne'

you can use python module plataform, to get the current OS and then make a solution for each platform:

import platform
platform.platform()
'Linux-3.3.0-8.fc16.x86_64-x86_64-with-fedora-16-Verne'
攒一口袋星星 2024-10-25 02:42:14

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

Here's how you can do it on 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)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文