如何在不阻塞整个应用程序的情况下读取单个击键?
How to read single keystrokes without blocking the whole application?
因为我没有找到更好的方法来读取命令行上的击键我目前正在使用 getch()
。
不幸的是,像这样使用 getch()
会停止 stdout
上的输出:
while True:
handle_keystroke(getch())
按下按钮会触发 handle_keystroke()
并在终端中打印 stdout
- 每次击键时逐行打印。
提供的建议 here 没有帮助。
我做错了什么?
顺便说一句:我 不需要 使用 getch()
。有没有更好的方法(例如使用select()
)?
更新:(更改标题)
所有这些只有在您使用多个线程时才会成为问题。所以看起来 getch
(这是一个非 Python 函数)没有释放 GIL,所以所有其他线程都被挂起,所以不仅 stdout
受到影响。
好的,找到了使用 select
而不是 getch()
的方法。诀窍是将 sys.stdout
的模式设置为 cbreak
:
import select
import tty
import termios
from contextlib import contextmanager
@contextmanager
def cbreak(stream):
"""Set fd mode to cbreak"""
old_settings = termios.tcgetattr(stream)
tty.setcbreak(stream.fileno())
yield
termios.tcsetattr(stream, termios.TCSADRAIN, old_settings)
with cbreak(sys.stdin):
while True:
select.select([sys.stdin], [], []) == ([sys.stdin], [], [])
key = sys.stdin.read(1)
handle_keystroke(key)
因为我没有找到更好的方法来读取命令行上的击键我目前正在使用 getch()
。
不幸的是,像这样使用 getch()
会停止 stdout
上的输出:
while True:
handle_keystroke(getch())
按下按钮会触发 handle_keystroke()
并在终端中打印 stdout
- 每次击键时逐行打印。
提供的建议 here 没有帮助。
我做错了什么?
顺便说一句:我 不需要 使用 getch()
。有没有更好的方法(例如使用select()
)?
更新:(更改标题)
所有这些只有在您使用多个线程时才会成为问题。所以看起来 getch
(这是一个非 Python 函数)没有释放 GIL,所以所有其他线程都被挂起,所以不仅 stdout
受到影响。
好的,找到了使用 select
而不是 getch()
的方法。诀窍是将 sys.stdout
的模式设置为 cbreak
:
import select
import tty
import termios
from contextlib import contextmanager
@contextmanager
def cbreak(stream):
"""Set fd mode to cbreak"""
old_settings = termios.tcgetattr(stream)
tty.setcbreak(stream.fileno())
yield
termios.tcsetattr(stream, termios.TCSADRAIN, old_settings)
with cbreak(sys.stdin):
while True:
select.select([sys.stdin], [], []) == ([sys.stdin], [], [])
key = sys.stdin.read(1)
handle_keystroke(key)