我正在编写一个简单的Python 3脚本,并且希望能够拦截终端窗口内的按键,以便根据返回的值执行某些操作。例如,
我也想要一个跨平台的解决方案。
我想重现这样的东西:
import msvcrt
key = ord(msvcrt.getch()) # Wait for a key to be pressed.
if key == 27: # The ESC key
print("You have pressed the ESC key!")
但是msvcrt
是Windows专用的模块,根据Python docs(和我的测试):
这些功能提供对Windows平台上某些有用功能的访问。
我找到了keyboard
模块,该模块非常易于使用(并且 more 跨平台),但是我没有设法仅捕获按下的键>在终端窗口内部。
例如:
import keyboard as kb
key = kb.read_hotkey()
if key == "esc": # The ESC key
print("You have pressed the ESC key!")
上面给出的代码不仅在执行脚本的终端窗口聚焦时拦截按键,而且在没有聚焦时也拦截按键。
因此,总而言之,您是否知道一种在执行脚本的终端窗口内(而不是外部)截取按键的有效方式(类似于 input()
,而无需按Enter < / em>),以及哪个是跨平台的(至少与GNU / Linux和Windows兼容)?
预先感谢您的回答,
问候,
亚历克西斯。
答案 0 :(得分:0)
这是部分解决方案,可以在Windows上使用,并且可以在GNU / Linux上使用。
我注意到,在GNU / Linux(至少在Debian 9上)上,相同的数字被分配给箭头键和ESC键。
对于以下代码,我受this主题解决方案的启发。
# coding: utf8
import sys
def read() -> int:
if sys.platform == "win32":
import msvcrt
key = ord(msvcrt.getch()) # Wait for a key to be pressed.
elif sys.platform == "linux":
import tty
import termios
try:
orig_settings = termios.tcgetattr(sys.stdin)
tty.setcbreak(sys.stdin)
key = ord(sys.stdin.read(1)[0])
except KeyboardInterrupt:
key = 3 # The code for Ctrl+C got on Windows.
finally: # To make sure that the terminal will return to its original state.
termios.tcsetattr(sys.stdin, termios.TCSADRAIN, orig_settings)
else:
raise RuntimeError("Your platform is not supported")
return key
if read() == 27: # The ESC key (also the UP-DOWN-RIGHT-LEFT on GNU/Linux)
print("You have pressed the ESC key!")
致谢,
亚历克西斯。
答案 1 :(得分:0)
看看curses模块。它在python标准库中,但不支持现成的Windows。 您可以查看一个定期维护的名为“ windows-curses”的项目。我尚未对其进行测试,但是据说它可以让您在Windows上使用python curses模块。 https://pypi.org/project/windows-curses/
import curses
def listen(window):
while True:
key = window.getch()
window.addstr(f'You pressed the "{key}" key!\n')
if key == 'q':
break
handle_keypress(key)
curses.wrapper(listen)
如果curses方法对您不起作用,或者您仍然需要更多粒度,则可以相当轻松地推出自己的跨平台方法。您可以尝试这样的事情:
from sys import platform
class Keyboard:
def __new__(cls):
if platform in ['Windows', 'win32', 'cygwin']:
cls = winKeyboard
elif platform in ['Mac', 'darwin', 'os2', 'os2emx']:
cls = MacKeyboard
else:
raise Exception(f'Unrecognized platform, {platform}')
return super(Keyboard, cls).__new__(cls)
def listen(self):
while True:
key = self.getch()
print(f'You pressed the "{key}" key!')
if key == 27:
break
return self.handle_key(key)
class MacKeyboard(Keyboard):
def getch(self):
implement_mac_logic()
class WinKeyboard(Keyboard):
def getch(self):
implement_win_logic()
keyboard = Keyboard()
keyboard.listen()
键盘。__new__会在运行时为当前操作系统提供适当的解决方案。
无论活动窗口如何,此方法仍将注册按键。
为此,您将需要访问活动窗口,这是另一个特定于OS的过程。
看看这个:https://stackoverflow.com/a/36419702/1420455
您可以实现检查当前窗口名称的功能
class Keyboard:
...
def listen(self):
while True:
if self.get_active_window() != desired_window:
continue
key = self.getch()
print(f'You pressed the "{key}" key!')
if key == 27:
break
return self.handle_key(key)
然后,您可以只在WinKeyboard.get_active_window和MacKeyboard.get_active_window中实现适当的逻辑 这不会考虑到在不同的选项卡中。这可能是可行的,但是我对这些API并不熟悉,无法告诉您。
还有诸如pygame之类的选项,它们将要求您创建和管理自己的窗口,但将满足您的要求。
编辑:将WinKeyboard和MacKeyboard更改为从Keyboard继承。