K.S*_*eff 8 python linux stdin buffering
我需要在Python中将标准输入切换到非缓冲模式,以便我可以读取它的单个字符.我设法让它工作,但现在标准输出被打破:不知何故,似乎在换行符后,发出一些空格字符,第一行为零,第二行为3,第三行为6,等等,这样:
ASD
ASD
ASD
Run Code Online (Sandbox Code Playgroud)
操作系统是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)
Run Code Online (Sandbox Code Playgroud)
当我在寻找同一个问题的答案时,谷歌把我带到了这里.没有回车的halex分享的线索有助于我寻找真相.我发现我的回答对克里斯的Wiki,一个帖子:https://utcc.utoronto.ca/~cks/space/blog/unix/CBreakAndRaw这导致我在这里读tty.py来源:https://开头汞柱. python.org/cpython/file/618ea5612e83/Lib/tty.py 这让我得出的结论是,如果目标是读取单个字符,而不是:
tty.setraw()
Run Code Online (Sandbox Code Playgroud)
使用:
tty.setcbreak()
Run Code Online (Sandbox Code Playgroud)
您遇到的问题是'raw','cooked'和'cbreak'模式之间的区别.这些模式是内核级终端驱动程序的模式,而不是应用程序代码或标准库的模式或用户空间中的任何其他模式.这是老派的Unix方式.虽然Posix属性通常与辅助函数一起翻转,模仿旧的'raw','cooked'和'cbreak'模式,但Posix已经用更细粒度的属性替换了它们.
在熟食模式下,终端驱动程序本身具有内置的原始行编辑功能.它处理退格,字擦除(基本上是一次整个单词的退格)和类似的事情.没有什么比处理箭头键或历史或类似的东西更复杂.非常原始.在这种模式下,你的程序永远不会从终端看到任何东西,直到发送行尾(eol)字符,然后你的程序得到整行,并且行结束被转换为Unix标准,\n
而不管终端实际上是什么确实.此外,作为其中的一部分,终端驱动程序将键入的字符回送到终端,以便用户可以看到他们正在键入的内容.
在'cooked'模式下,内核级终端驱动程序也进行一些输出转换.如果需要,其中一部分正在\n
变成\r\n
现实.
此外,在'cooked'模式下,终端驱动程序处理特殊字符,如Control-C(将SIGINT发送到控制进程组(由CPython转换为KeyboardInterrupt异常))和Control-Z(发送SIGTSTP(如SIGSTOP,但是可以被捕获到控制过程组).
在"cbreak"模式下,不再进行行编辑.终端驱动程序立即将每个字符(或短字符序列,如箭头键的转义序列)提供给程序.这些字符不会回显到屏幕上,因此除非您的程序打印出来,否则用户将看不到它们.尽管终端驱动程序仍然处理诸如退格或字擦除字符(通常是Control-W)之类的行编辑字符,但终端驱动程序仍会处理像Control-C和Control-Z这样的特殊字符.此外,一些输出处理仍然完成,因此驱动程序变为\n
a \r\n
.
在"原始"模式下,不对输入或输出进行任何处理.无特殊字符处理,没有呼应,没有转化\n
成\r\n
,不应对用于控制-Z,什么都没有.由终端进入原始模式的程序可以完成所有操作.
现在,您正在设置属性,sys.stdin
因此您可能认为这不应该影响sys.stdout
.但实际上,两个文件描述符都会导致终端驱动程序完全相同的"实例".它是终端驱动程序的设置,用于确定发生的情况.因此,如果您通过sys.stdin
,sys.stdout
甚至sys.stderr
更改相同的底层终端驱动程序实例更改这些设置并且它们会影响所有其他设置并不重要.
当然,对于在程序启动之前已由shell重定向的文件描述符,情况并非如此.
归档时间: |
|
查看次数: |
2808 次 |
最近记录: |