原始模式下的Python stdin print增加了空格

时间:2012-09-01 22:05:32

标签: python linux stdin buffering

我需要在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)

3 个答案:

答案 0 :(得分:8)

当我在寻找同一个问题的答案时,谷歌把我带到了这里。没有回车的halex分享的线索有助于我寻找真相。我在Chris的一篇文章中找到了我的答案:https://utcc.utoronto.ca/~cks/space/blog/unix/CBreakAndRaw让我在这里阅读了tty.py的来源:https://hg.python.org/cpython/file/618ea5612e83/Lib/tty.py 这让我得出的结论是,如果目标是阅读单个字符,而不是:

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。但是,事实上,你的两个文件描述符都会导致完全相同的实例&#39;终端司机。它是确定发生了什么的终端驱动程序的设置。因此,如果您通过sys.stdinsys.stdout甚至sys.stderr更改这些设置并不重要,则所有更改相同的基础终端驱动程序实例都会影响所有其他设置。< / p>

当然,对于在程序启动之前已由shell重定向的文件描述符,情况并非如此。

作为旁注,您可以使用命令行上的stty -a查看所有这些标志的完整读数(包括哪些控制字符会导致cooked和cbreak模式中的哪些信号)。

答案 2 :(得分:5)

看起来你只是换行,但没有回车。将您的打印更改为

print("ASD", end="\r\n")