Python3无法覆盖sys.stdin获取终端光标位置问题求助
问题原因
- 终端对
\x1b[6n转义序列的响应是直接写入stdin对应的底层文件描述符,不会触发Python层sys.stdin对象的自定义write方法,且stdin本身是只读流,你自定义的write方法本身不会被调用。 - 终端默认开启行缓冲和输入回显,响应内容不会立即传递给进程,还会直接打印到终端界面上。
正确实现(类Unix系统)
通过termios和tty模块临时修改终端属性,读取响应后立即恢复原有配置,避免终端状态异常:
import sys import tty import termios import re def get_cursor_pos(): fd = sys.stdin.fileno() # 保存终端原始属性 old_attr = termios.tcgetattr(fd) try: # 开启cbreak模式,关闭行缓冲和输入回显 tty.setcbreak(fd) # 发送查询转义序列,强制刷新确保立即发送 sys.stdout.write("\x1b[6n") sys.stdout.flush() # 读取完整响应,响应格式为 \x1b[行号;列号R buf = "" while not buf.endswith("R"): buf += sys.stdin.read(1) # 解析行列数值 match = re.match(r"\x1b\[(\d+);(\d+)R", buf) if match: return int(match.group(1)), int(match.group(2)) return (0, 0) finally: # 强制恢复终端原始属性 termios.tcsetattr(fd, termios.TCSADRAIN, old_attr) # 调用示例 row, col = get_cursor_pos() print(f"光标位置:行 {row},列 {col}")
Windows系统兼容实现
Windows系统没有termios模块,可以直接调用Win32 API获取光标位置:
import ctypes from ctypes import wintypes class COORD(ctypes.Structure): _fields_ = [("X", wintypes.SHORT), ("Y", wintypes.SHORT)] class CONSOLE_SCREEN_BUFFER_INFO(ctypes.Structure): _fields_ = [ ("dwSize", COORD), ("dwCursorPosition", COORD), ("wAttributes", wintypes.WORD), ("srWindow", wintypes.SMALL_RECT), ("dwMaximumWindowSize", COORD), ] def get_cursor_pos(): kernel32 = ctypes.WinDLL("kernel32", use_last_error=True) hconsole = kernel32.GetStdHandle(-11) # STD_OUTPUT_HANDLE常量 info = CONSOLE_SCREEN_BUFFER_INFO() if not kernel32.GetConsoleScreenBufferInfo(hconsole, ctypes.byref(info)): raise ctypes.WinError(ctypes.get_last_error()) # Windows默认行号从0开始,这里转换为和ANSI规范一致的1起始编号 return info.dwCursorPosition.Y + 1, info.dwCursorPosition.X + 1
你可以根据运行平台判断调用对应实现即可。
内容的提问来源于stack exchange,提问作者DarviL
相关产品推荐
相关产品推荐

