我需要在Python中将标准输入切换到非缓冲模式,以便我可以读取它的单个字符。我设法让它工作,但现在标准输出被打破:不知何故,似乎在换行字符后,发出一些空格字符,第一行为零,第二行为3,第三行为6,等等,这样:
ASD
ASD
ASD
操作系统是Ubuntu Linux 12.04,64位版本,Python版本是3.2.3。
如何摆脱这种行为?
以下是我用过的代码:
import sys
import tty
import termios
fd = sys.stdin.fileno()
old_settings = termios.tcgetattr(fd)
tty.setraw(sys.stdin)
for i in range(0, 10):
print("ASD")
termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
答案 0 :(得分:8)
tty.setraw()
使用:
tty.setcbreak()
答案 1 :(得分:8)
您遇到的问题是' raw',' cooked'和' cbreak'模式。这些模式是内核级终端驱动程序的模式,而不是应用程序代码或标准库的模式或用户空间中的任何其他模式。这是老派的Unix方式。虽然Posix属性通常与辅助函数一起翻转,模仿旧的' cooked' cooked&#39,但Posix已经用更细粒度的属性替换它们。 ;和' cbreak'模式。
在熟食模式下,终端驱动程序本身具有内置的原始行编辑功能。它处理退格,字擦除(基本上是一次整个单词的退格)和类似的事情。没有什么比处理箭头键或历史或类似的东西更复杂。非常原始。在这种模式下,你的程序永远不会从终端看到任何东西,直到发送行尾(eol)字符,然后你的程序得到整行,并且行结束被转换为Unix标准\n
无论如何终端实际上做了什么。此外,作为其中的一部分,终端驱动程序将键入的字符回送到终端,以便用户可以看到他们正在键入的内容。
煮熟的'模式,内核级终端驱动程序也做一些输出转换。如果需要,部分原因是将\n
转变为\r\n
。
此外,在'煮熟'模式终端驱动程序处理特殊字符,如Control-C(将SIGINT发送到控制进程组(由CPython转换为KeyboardInterrupt异常))和Control-Z(发送SIGTSTP(如SIGSTOP,但可以捕获)到控制过程组)。
在' cbreak'模式,不再进行行编辑。终端驱动程序立即将每个字符(或短字符序列,如箭头键的转义序列)提供给程序。这些字符不会回显到屏幕上,因此除非您的程序打印出来,否则用户将无法看到它们。尽管终端驱动程序仍然处理诸如退格或字擦除字符(通常是Control-W)之类的行编辑字符,但终端驱动程序仍会处理像Control-C和Control-Z这样的特殊字符。此外,某些输出处理仍然完成,因此驱动程序将\n
变为\r\n
。
' raw'模式,不对输入或输出进行处理。没有特殊的字符处理,没有回显,没有转换\n
到\r\n
,没有处理Control-Z,没有。它取决于将终端置于原始模式的程序来完成所有工作。
现在,您要设置sys.stdin
的属性,以便您可能认为这不应影响sys.stdout
。但是,事实上,你的两个文件描述符都会导致完全相同的实例'终端司机。它是确定发生了什么的终端驱动程序的设置。因此,如果您通过sys.stdin
,sys.stdout
甚至sys.stderr
更改这些设置并不重要,则所有更改相同的基础终端驱动程序实例都会影响所有其他设置。< / p>
当然,对于在程序启动之前已由shell重定向的文件描述符,情况并非如此。
作为旁注,您可以使用命令行上的stty -a
查看所有这些标志的完整读数(包括哪些控制字符会导致cooked和cbreak模式中的哪些信号)。
答案 2 :(得分:5)
看起来你只是换行,但没有回车。将您的打印更改为
print("ASD", end="\r\n")