在Python 3中禁用sys.stdin的缓冲
我试图禁用stdin缓冲,以便读取ANSI代码在Python 3中禁用sys.stdin的缓冲,python,python-3.x,Python,Python 3.x,我试图禁用stdin缓冲,以便读取ANSI代码\033[6n(应该报告光标位置)的响应 我按照回答中的建议尝试了stdin\u ub=os.fdopen(stdin.fileno(),'rb',buffering=0),但程序仍然在第一次尝试读取的第ch=stdin\u ub.read(1)行被阻塞。当在终端中键入return时,它会解除阻塞,这表明stdin仍然是行缓冲的 以下是完整的代码供参考: def getpos(): stdin_ub = os.fdopen(sys.stdin
\033[6n
(应该报告光标位置)的响应
我按照回答中的建议尝试了stdin\u ub=os.fdopen(stdin.fileno(),'rb',buffering=0)
,但程序仍然在第一次尝试读取的第ch=stdin\u 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不幸的是,没有可移植的方法来实现这一点。在普通操作系统(例如Windows和Unix系列)上,从键盘读取时,底层IO系统是行缓冲的 curses模块将提供一种几乎可移植的方式来控制行规程,不幸的是,它在windows系统上不起作用 如果你能使用它,你就必须使用它
curses.noecho()
curses.raw() # or curses.cbreak()
进入原始模式(通常应设置回波)
及
不幸的是,要恢复正常,没有可移植的方法。在普通操作系统(例如Windows和Unix系列)上,从键盘读取时,底层IO系统是行缓冲的 curses模块将提供一种几乎可移植的方式来控制行规程,不幸的是,它在windows系统上不起作用 如果你能使用它,你就必须使用它
curses.noecho()
curses.raw() # or curses.cbreak()
进入原始模式(通常应设置回波)
及
要恢复到正常状态,技巧是使用
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]))
诀窍是使用
tty.setcbreak(sys.stdin.fileno(),termios.TCSANOW)
并在此之前通过变量termios.getattr
存储终端属性,以恢复默认行为。使用cbreak
set,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]))
从
os.fdopen(sys.stdin.fileno(),'rb'中的'rb'
中删除b
)
?@MoonCheesez你有没有读到我在使用python 3?:p只是在冒险猜测。'b'
通常意味着缓冲区,因此删除它可能会有所帮助。@MoonCheesez猜测不起作用。需要5秒钟来验证你的建议是错误的,因为它会产生错误,那么你为什么一直在浪费时间进行随机猜测?@MoonCheesez另外,“b
通常意味着缓冲区”是错误的。如果您不确定您的声明,请不要评论/回答。从os.fdopen(sys.stdin.fileno(),'rb'中的'rb'
中删除b
)
?@MoonCheesez你有没有读到我在使用python 3?:p只是在冒险猜测。'b'
通常意味着缓冲区,因此删除它可能会有所帮助。@MoonCheesez猜测不起作用。需要5秒钟来验证你的建议是错误的,因为它会产生错误,那么你为什么一直在浪费时间进行随机猜测?@MoonCheesez另外,“b
通常表示缓冲区”是错误的。如果您不确定您的声明,请不要评论/回答。使用curses的问题是它需要您运行curses.initscr()
,这会导致清除终端不必要的副作用使用curses的问题是需要运行curses.initscr()
,这会导致清除终端不必要的副作用