Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/331.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
原始模式下的Python stdin print添加空格_Python_Linux_Stdin_Buffering - Fatal编程技术网

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

原始模式下的Python stdin print添加空格,python,linux,stdin,buffering,Python,Linux,Stdin,Buffering,我需要在Python中将标准输入切换到非缓冲模式,这样我就可以从中读取单个字符。我设法让它工作,但现在标准输出被破坏了:不知何故,在换行符之后,一些空格字符被释放,第一行为零,第二行为3,第三行为6,等等,如下所示: ASD 自闭症 自闭症 操作系统是Ubuntu Linux 12.04,64位版本,Python版本是3.2.3 我怎样才能摆脱这种行为 下面是我使用的代码: import sys import tty import termios fd = sys.stdin.fileno(

我需要在Python中将标准输入切换到非缓冲模式,这样我就可以从中读取单个字符。我设法让它工作,但现在标准输出被破坏了:不知何故,在换行符之后,一些空格字符被释放,第一行为零,第二行为3,第三行为6,等等,如下所示:

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)

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

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

当我在搜索同一个问题的答案时,谷歌把我带到了这里。halex分享的没有马车返回的线索有助于我寻找真相。我在Chris的Wiki上的一篇帖子中找到了我的答案:这让我在这里阅读了tty.py的来源: 这让我得出结论,如果目标是阅读单个字符,而不是:

tty.setraw()
使用:


您遇到的问题是“生”、“熟”和“cbreak”模式之间的差异。这些模式是内核级终端驱动程序的模式,而不是应用程序代码、标准库或用户空间中的任何其他模式。这是指这些的老派Unix方式。Posix已经用更细粒度的属性集取代了它们,尽管Posix属性通常与辅助函数一起翻转,以模仿旧的“原始”、“烹饪”和“cbreak”模式

在烹调模式下,终端驱动程序本身具有内置的基本行编辑功能。它处理退格、单词擦除(基本上一次退格一个单词)和类似的事情。没有什么比处理箭头键或历史记录之类的更复杂的了。非常原始。在此模式下,在发送行结束(eol)字符之前,您的程序不会从终端看到任何东西,然后您的程序会得到一整行,并且无论终端实际做什么,行尾都会转换为Unix标准
\n
。此外,作为这项工作的一部分,终端驱动程序将键入的字符回显到终端,以便用户可以看到他们键入的内容

在“煮熟”模式下,内核级终端驱动程序还执行一些输出转换。其中的一部分是在需要时将
\n
转换为
\r\n

此外,在“煮熟”模式下,终端驱动程序处理特殊字符,如Control-C(向控制进程组发送SIGINT(由CPython转换为键盘中断异常))和Control-Z(向控制进程组发送SIGTSTP(如SIGSTOP,但可以捕获)

在“cbreak”模式下,不再进行行编辑。终端驱动程序立即向程序提供每个字符(或短字符序列,如箭头键的转义序列)。这些字符不会回显到屏幕上,因此,除非您的程序随后打印它们,否则用户不会看到它们。尽管终端驱动程序不再处理诸如退格或字擦除字符(通常为Control-W)之类的行编辑字符,但它仍然处理诸如Control-C和Control-Z之类的特殊字符。此外,一些输出处理仍然完成,因此驱动程序将
\n
转换为
\r\n

在“原始”模式下,输入或输出均不进行任何处理。没有特殊字符处理,没有回音,没有将
\n
转换为
\r\n
,没有对Control-Z的处理,没有任何内容。这取决于将终端置于原始模式的程序来完成这一切

现在,您正在为
sys.stdin
设置属性,因此您可能认为这不会影响
sys.stdout
。但是,事实上,两个文件描述符都会导致完全相同的终端驱动程序“实例”。终端驱动程序的设置决定了会发生什么。因此,如果您通过
sys.stdin
sys.stdout
,甚至是
sys.stderr
,更改这些设置并不重要,它们都会更改相同的底层终端驱动程序实例,并影响所有其他实例

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


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

到目前为止,这似乎是正确的;我的印象是,我永远不应该在Linux下手动插入
\r
。Thanks@halex您能解释一下为什么在原始模式下需要这样做,而在正常打印时不需要这样做吗?谢谢。这是一个比我更好更详细的答案+1@TheDavidFactor-我错过的一件事是,显然posix已经在很大程度上取消了驱动程序级别的谨慎模式,而是将这些模式转变为基本独立的标志的细粒度集合。
tty.setcbreak()