检测到EOF时未读取最后一行stdin

时间:2016-02-05 03:25:27

标签: python stdin

可能是一个简单的问题,但我基本上试图复制cat命令的行为(非常稀疏和简单),但是在python中。我希望用户能够输入他们想要的所有文本,然后当他们输入EOF时(按ctrl+dcmd+d),程序应该打印出他们输入的所有内容。

import sys
for line in sys.stdin:
    print line

如果我输入输入行并使用返回字符跟在最后一行,然后按cmd+d

never gonna give you up
never gonna let you down
never gonna run around
and desert you

然后输出

never gonna give you up
never gonna let you down
never gonna run around
and desert you

但是,如果我在最后一行时按cmd+d并且#34; and desert you"然后输出是:

never gonna give you up
never gonna let you down
never gonna run around

如何修改程序,以便在用户按下最后一行的EOF时,它仍应作为输出的一部分包含在内?

3 个答案:

答案 0 :(得分:2)

好的,这很奇怪但事实证明有一个解释。 ctrl-d"传输结束" (EOT),而不是EOF。这意味着特定于环境,但对于* nix终端,它意味着立即将输入缓冲区刷新到程序。

如果缓冲区中有字符,python的stdin会获取它们,但由于没有\n,stdin迭代器会缓冲它们并且还没有发出任何内容。

如果缓冲区中没有字符,python的stdin将获得一个空缓冲区,而python遵循空缓冲区意味着EOF并且应该停止迭代的规则。

如果您输入一些字符,然后连续输入2个ctrl-d,您将获得缓冲的字符,迭代将结束。并且,为了使事情尽可能复杂,如果你开始另一个for line in sys.stdin,它将很乐意继续接受输入。

修改

当您使用输入缓冲区中的数据点击ctrl-d时,此脚本会立即为您提供任何待处理字符,但除非您点击第二个ctrl-d

,否则它不会知道退出
import sys

while True:
    c = sys.stdin.read(1)
    if not c:
        break
    sys.stdout.write(c)
    sys.stdout.flush()

答案 1 :(得分:2)

Control-D的行为实际上是操作系统的TTY驱动程序的功能,而不是Python的功能。 TTY驱动程序通常一次将数据发送到整行程序。你会注意到'cat'和大多数其他程序的行为方式相同。

做你所要求的是非平凡的。它通常需要将TTY置于原始模式,读取和处理数据(您将获得Control-D字符本身),然后在退出之前将其从原始模式中取出(您不想以原始模式退出!)< / p>

这样做的程序依赖于操作系统,但您可以使用tty.setraw()和tty.setcbreak()。

答案 2 :(得分:0)

我认为这是一个python 2.7问题。我在Python 3.5上尝试了你的代码,它运行得很好。

希望这有帮助!