我想以非阻塞的方式立即在命令行上捕获"所有"键盘输入(无需等待新行)。
此问题演示如何使用 select()
以非阻塞方式读取stdin
。这是它的工作原理:
while True:
if select.select([sys.stdin], [], [], 0)[0] == [sys.stdin]:
print(sys.stdin.read(1))
... do other stuff ...
不幸的是,您只有在按 RETURN
后才能获得结果。
我的第一个猜测是stdin
只是行缓冲,所以在阅读这个问题后,我将我的代码变成了
ubuf_stdin = os.fdopen(sys.stdin.fileno(), 'rb', buffering=0)
while True:
if select.select([ubuf_stdin], [], [], 0)[0] == [ubuf_stdin]:
print(ubuf_stdin.read(1))
... do other stuff ...
这段代码效果更好 - 缓冲区被完全读取而不会中断 - 但它仍然等待RETURN
被按下。
我也试图detach
stdin
:
ubuf_stdin = os.fdopen(sys.stdin.detach().fileno(), 'rb', buffering=0)
按键后如何立即对键盘输入做出反应?
使用 getch
模块一次获取一次一次按键,如本问题中所述。
我不认为你能够以一种非阻塞但一次字符的方式阅读 stdin,它真的不是为了这个目的。
这个可以做到,但它有一些缺点:
- 使用对我来说似乎有点重的
curses
模块 - 输入必须轮询 - 尚无法
select()
。 - 键盘输入仍会打印到终端
.. 但它:)有效。
import curses
def read_stdin(self):
def cb(screen):
result = []
screen.nodelay(1)
while True:
try:
result.append(screen.getkey())
except curses.error:
return result
# contains a list of keys pressed since last call
return curses.wrapper(cb)