我需要在python终端程序中监听某些按键,而不会暂停执行raw_input
。我已经看到人们使用一些窗口特定的方式来听取击键,我看到人们使用像tkinter和pygame这样的大模块,我想避免使用。
是否有一个轻量级模块可以实现这个跨平台(至少是ubuntu,windows,mac)?或者有没有办法只使用来自tkinter,pygame等的事件系统......?
如果没有,我应该怎样处理这个问题?我的第一个想法是将stdin重定向到另一个进程并继续检查它是否包含我的一个事件键。
感谢@unutbu花时间将这个问题标记为3年,并成功回答了另一个问题的副本,其答案不适用于此问题,因为我特别询问了非阻塞解决方案。
答案 0 :(得分:7)
我不知道任何侦听按键的跨平台轻量级模块。但是如果你想要实现一些简单的事情,这里有一个建议:
在Python常见问题解答中查看getting a single keypress at a time上的这个问题。您可以尝试阻止来自sys.stdin
和threading
的读取。但这可能仅适用于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)