-2

我一直在使用这样的课程。到目前为止,它对我来说一直运行良好,但是由于我正在从外部源轮询输入,因此我的程序并没有接受每一个键。这是代码及其输出的粗略示例。

while True:
    ch = getch()
    print "Queue: " + ch
    # Do something #

输出为

Queue: 0
Queue: 01
Queue: 012
3Queue: 012
Queue: 0124

我知道可能有几个解决方案,主要是那些需要在该#Do Something#部分下使代码更高效的解决方案。但是,我已将其缩小到任何两个getch()调用之间的空间尽可能最小化的程度。有什么建议么?

4

1 回答 1

1

您特意选择了一个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))

然后,您可以查看termiosPython 模块、联机帮助页和 C 标头 ( /usr/include/sys/termios.h),以了解每个字段中每个不同位的含义。

于 2013-06-10T23:29:13.537 回答