我尝试getch()
在 Python 中实现函数,它还应该返回特殊键(如 F1-F12 和箭头键)的字符列表。这些特殊键按顺序生成多个字符。因此getch()
在阻塞模式下读取一个字符,然后应该检查输入缓冲区中是否还有额外的字符来获取它们。
我将ioctl
call 与termios.FIONREAD一起使用来获取输入缓冲区中的字节数。它会捕获堆积在缓冲区中的非特殊按键,但会丢失特殊键中的额外符号。似乎有两个不同的缓冲区,如果有人可以解释这一点,那就太好了。
这是交互式示例:
from time import sleep
def getch():
import sys, tty, termios
fd = sys.stdin.fileno()
# save old terminal settings, because we are changing them
old_settings = termios.tcgetattr(fd)
try:
# set terminal to "raw" mode, in which driver returns
# one char at a time instead of one line at a time
#
# tty.setraw() is just a helper for tcsetattr() call, see
# http://hg.python.org/cpython/file/c6880edaf6f3/Lib/tty.py
tty.setraw(fd)
ch = sys.stdin.read(1)
# --- check if there are more characters in buffer
from fcntl import ioctl
from array import array
sleep(1)
buf = array('i', [0])
ioctl(fd, termios.FIONREAD, buf)
print "buf queue: %s," % buf[0],
# ---
finally:
# restore terminal settings. Do this when all output is
# finished - TCSADRAIN flag
termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
return ch
char = ''
while char != 'q':
char = getch()
print 'sym: %s, ord(%s)' % (char, ord(char))
注意sleep(1)
中间。如果您在这一秒到期之前按下一个键,输出将是:
buf queue: 0, sym: l, ord(108)
对于一秒钟内输入的 5 个普通键(例如 'asdfg'),输出为:
buf queue: 4, sym: a, ord(97)
但对于单个箭头键,输出:
buf queue: 0, sym: , ord(27)
buf queue: 0, sym: [, ord(91)
buf queue: 0, sym: D, ord(68)
这里有两个问题:
为什么普通按键队列中的4个符号被丢弃?是因为切换到“原始”终端模式吗?
getch()
如何在不让终端处于“原始”模式的情况下为后续运行保留字符?为什么
ioctl
单个特殊按键的缓冲区为空?这些角色是从哪里来的后续getch()
运行?如何检查它们?