gpt4 book ai didi

python - 在 Python 3 中禁用 sys.stdin 的缓冲

转载 作者:行者123 更新时间:2023-12-02 17:27:10 28 4
gpt4 key购买 nike

我正在尝试禁用标准输入缓冲,以便读取 ANSI 代码 \033[6n 的响应(应该报告光标位置)。

我按照答案 Setting smaller buffer size for sys.stdin? 中的建议尝试了 stdin_ub = os.fdopen(stdin.fileno(), 'rb', buffering=0) ,但程序仍然在第一次尝试读取的 ch = stdin_ub.read(1) 行被阻塞。当在终端中键入 return 时,它会解除阻塞,这表明 stdin 仍然是行缓冲的。

作为引用,这里是完整的代码:

def getpos():
stdin_ub = os.fdopen(sys.stdin.fileno(), 'rb', buffering=0)
sys.stdout.write('\033[6n')
sys.stdout.flush()
ch, k, field = None, -1, [b'', b'']
while True:
#print('reading wait...')
ch = stdin_ub.read(1)
#print('reading OK')
if ch == b'[': k = 0
elif ch == b';': k = 1
elif ch == b'R': break
elif k >= 0: field[k] += ch
try:
return tuple(map(int, field))
except:
pass

我正在使用 python 3.5.1

最佳答案

诀窍是使用 tty.setcbreak(sys.stdin.fileno(), termios.TCSANOW) 并在此之前通过 termios.getattr 将终端属性存储在变量以恢复默认行为。使用 cbreak 设置,sys.stdin.read(1) 是无缓冲的。这也抑制了来自终端的 ansi 控制代码响应。

def getpos():

buf = ""
stdin = sys.stdin.fileno()
tattr = termios.tcgetattr(stdin)

try:
tty.setcbreak(stdin, termios.TCSANOW)
sys.stdout.write("\x1b[6n")
sys.stdout.flush()

while True:
buf += sys.stdin.read(1)
if buf[-1] == "R":
break

finally:
termios.tcsetattr(stdin, termios.TCSANOW, tattr)

# reading the actual values, but what if a keystroke appears while reading
# from stdin? As dirty work around, getpos() returns if this fails: None
try:
matches = re.match(r"^\x1b\[(\d*);(\d*)R", buf)
groups = matches.groups()
except AttributeError:
return None

return (int(groups[0]), int(groups[1]))

关于python - 在 Python 3 中禁用 sys.stdin 的缓冲,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37726138/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com