在Python中查找箭头键的值:为什么是三元组?
我正在尝试找出我的电脑系统给方向键分配的值,特别是在Python中。我用以下脚本来实现这个目的:
import sys,tty,termios
class _Getch:
def __call__(self):
fd = sys.stdin.fileno()
old_settings = termios.tcgetattr(fd)
try:
tty.setraw(sys.stdin.fileno())
ch = sys.stdin.read(1)
finally:
termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
return ch
def get():
inkey = _Getch()
while(1):
k=inkey()
if k!='':break
print 'you pressed', ord(k)
def main():
for i in range(0,25):
get()
if __name__=='__main__':
main()
然后我运行了这个脚本,按下了上、下、左、右方向键,得到了这个输出:
$ python getchar.py
you pressed 27
you pressed 91
you pressed 65
you pressed 27
you pressed 91
you pressed 66
you pressed 27
you pressed 91
you pressed 67
you pressed 27
you pressed 91
you pressed 68
这个结果有点奇怪,因为它显示方向键在我的系统上被记录为某种三元组(27-91-6x),每次按下一个方向键都会调用三次get()。相比之下,按下字母a、b、c和CTRL-C的结果是:
you pressed 97
you pressed 98
you pressed 99
you pressed 3
有没有人能告诉我,为什么我的方向键的值看起来像是以三元组的形式存储的?这是为什么呢?在所有平台上都是这样吗?(我使用的是Debian Linux。)如果不是,我应该如何存储方向键的值呢?
我最终的目标是写一个程序,能够正确识别方向键,并根据按下的是哪个方向键来执行相应的功能。
3 个回答
这里有一个小变种的解决方案,它可以同时读取普通字符和方向键。
import sys
import select
import tty
import termios
def isData():
return select.select([sys.stdin], [], [], 0) == ([sys.stdin], [], [])
old_settings = termios.tcgetattr(sys.stdin)
try:
tty.setcbreak(sys.stdin.fileno())
while 1:
if isData():
k = sys.stdin.read(1)
if k == 'q':
break
elif k=='\x1b':
kk = sys.stdin.read(2)
if kk == 'OA':
print("up")
elif kk=='OB':
print("down")
elif kk=='OC':
print("right")
elif kk=='OD':
print("left")
else:
print("-->", kk.encode('unicode_escape'))
else:
print("char pressed: ", k)
finally:
termios.tcsetattr(sys.stdin, termios.TCSADRAIN, old_settings)
我在使用Mac电脑,写了以下代码,效果很好:我得到了方向键的值,分别是0、1、2、3(上、下、左、右)。另外,记住ESC键的代码是27也很重要。祝好!
while True:
key = cv2.waitKey(1) & 0xFF
# if the 'ESC' key is pressed, Quit
if key == 27:
quit()
if key == 0:
print "up"
elif key == 1:
print "down"
elif key == 2:
print "left"
elif key == 3:
print "right"
# 255 is what the console returns when there is no key press...
elif key != 255:
print(key)
我想我搞明白了。
我从这里了解到,每个方向键都有一个独特的ANSI转义码。然后我发现这些ANSI转义码在不同的系统和应用中是不同的:在我的终端里,输入cat
并按上箭头会得到^[[A
,而在C语言中,它似乎是\033[A
,等等。后面的部分[A
是一样的,但前面的Escape
码可以用十六进制(以x开头)、八进制(以0开头)或十进制(没有前缀数字)表示。
接着我打开了Python控制台,把之前得到的三个字符输入进去,试图找出它们的字符值。结果发现,chr(27)
返回\x1b
,chr(91)
返回[
,而调用chr
对65,66,67,68
则分别返回A,B,C,D
。这样就清楚了:\x1b
就是那个转义码!
然后我注意到,ANSI表示的一个箭头键是由三个字符组成的,所以我需要修改我的代码,以便一次读取三个字符。以下是结果:
import sys,tty,termios
class _Getch:
def __call__(self):
fd = sys.stdin.fileno()
old_settings = termios.tcgetattr(fd)
try:
tty.setraw(sys.stdin.fileno())
ch = sys.stdin.read(3)
finally:
termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
return ch
def get():
inkey = _Getch()
while(1):
k=inkey()
if k!='':break
if k=='\x1b[A':
print "up"
elif k=='\x1b[B':
print "down"
elif k=='\x1b[C':
print "right"
elif k=='\x1b[D':
print "left"
else:
print "not an arrow key!"
def main():
for i in range(0,20):
get()
if __name__=='__main__':
main()