您特意选择了一个getch
避免排队并且只抓取最新字符的实现。
您可以通过将部件移动到后台线程来更快地为输入提供服务# Do Something #
,或者使用类似事件循环的实现,在尝试处理队列中的第一个字符之前将所有可用字符排队,等等。但这些都不能保证您获取所有字符。
如果您想允许角色排队以确保您不会错过任何内容,只需……不要使用旨在不让他们排队的实现。
如果您不需要getch
在 2 秒后超时,您可以通过不调用select
. 这也意味着您不需要TCSADRAIN
. 此外,不要调用 ,而是setraw
尝试仅关闭您关心的标志。禁用ICANON
足以使其逐个字符地读取。
这是一个完整的测试:
import select
import sys
import termios
import time
import tty
def getch():
fd = sys.stdin.fileno()
old_settings = termios.tcgetattr(fd)
new_settings = old_settings[:]
new_settings[3] ~= ~termios.ICANON
try:
termios.tcsetattr(fd, termios.TCSANOW, new_settings)
ch=sys.stdin.read(1)
finally:
termios.tcsetattr(fd, termios.TCSANOW, old_settings)
return ch
while True:
ch = getch()
if ch == '\x03':
break
print "Queue: " + ch
time.sleep(1)
这是输出:
aQueue: a
bcdefgQueue: b
Queue: c
Queue: d
Queue: e
Queue: f
Queue: g
^CTraceback (most recent call last):
File "getch.py", line 24, in <module>
ch = getch()
File "getch.py", line 16, in getch
ch=sys.stdin.read(1)
KeyboardInterrupt
如果您确实想要超时,但又不想丢掉多余的字符,那很容易;只需使用termios
它来设置它,而不是围绕它进行结束运行:
new_settings[-1][termios.VTIME] = 20
new_settings[-1][termios.VMIN] = 0
现在输出如下所示:
aQueue: a
bcdQueue: b
Queue: c
Queue: d
Queue:
Queue:
^CTraceback (most recent call last):
File "getch.py", line 30, in <module>
time.sleep(1)
KeyboardInterrupt
还有更多选项termios
——如果你想要你正在使用的实现的无回显功能、^C-swallowing 等,请阅读手册页。
此外,如果您想确切了解具体setraw
操作,只需运行以下命令:
import sys, termios, tty
fd = sys.stdin.fileno()
o = termios.tcgetattr(fd)
tty.setraw(fd)
n = termios.tcgetattr(fd)
tcsetattr(fd, termios.TCSANOW, o)
print('iflag : {:10x} {:10x}'.format(o[0], n[0]))
print('oflag : {:10x} {:10x}'.format(o[1], n[1]))
print('cflag : {:10x} {:10x}'.format(o[2], n[2]))
print('lflag : {:10x} {:10x}'.format(o[3], n[3]))
print('ispeed: {:10d} {:10d}'.format(o[4], n[4]))
print('ospeed: {:10d} {:10d}'.format(o[5], n[5]))
print('cc :')
for i, (oo, nn) in enumerate(zip(o[6], n[6])):
print(' {:4d}: {:>10} {:>10}'.format(i, oo, nn))
然后,您可以查看termios
Python 模块、联机帮助页和 C 标头 ( /usr/include/sys/termios.h
),以了解每个字段中每个不同位的含义。