第一个问题是readlines 将所有行读入一个列表。在所有行都存在之前,它不能这样做,直到 stdin 达到 EOF。
但您实际上并不需要 list 行,只需要 一些可迭代 行。还有一个文件,比如sys.stdin,已经是这样一个可迭代的。而且它是一种懒惰的方法,只要它们可用就一次生成一行,而不是等待一次全部生成。
所以:
for line in sys.stdin:
print line
每当您发现自己在寻找readlines 时,问问自己是否真的需要它。答案总是是否定的。 (好吧,除非你想用参数调用它,或者在一些有缺陷的不完全类似文件的对象上调用它。)请参阅Readlines Considered Silly 了解更多信息。
但与此同时,还有一个秒问题。并不是 Python 正在缓冲它的 stdin,或者其他进程正在缓冲它的 stdout,而是文件对象迭代器本身正在做内部缓冲,这可能(取决于你的平台——但在大多数 POSIX 平台上,它通常会)阻止您在 EOF 之前到达第一行,或者至少在读取很多行之前。
这是 Python 2.x 的一个已知问题,已在 3.x 中修复,* 但除非您愿意升级,否则这对您没有帮助。
命令行和环境文档以及大多数系统的手册页中都提到了该解决方案,但隐藏在 -u flag documentation 的中间:
请注意,xreadlines()、readlines() 和文件对象迭代器(“for line in sys.stdin”)中有内部缓冲,不受此选项影响。要解决这个问题,您需要在“while 1:”循环中使用“sys.stdin.readline()”。
换句话说:
while True:
line = sys.stdin.readline()
if not line:
break
print line
或者:
for line in iter(sys.stdin.readline, ''):
print line
对于不同的问题,在this answer 中,Alex Martelli 指出您总是可以忽略sys.stdin 并重新fdopen 文件描述符。这意味着您将获得一个 POSIX fd 的包装器,而不是 C stdio 句柄。但这对于 this 问题来说既非必要也不充分,因为问题不在于 C stdio 缓冲,而在于 file.__iter__ 缓冲与其交互的方式。
* Python 3.x 不再使用 C stdio 库的缓冲;它自己做所有事情,在io 模块中的类型中,这意味着迭代器可以共享文件对象本身正在使用的同一个缓冲区。虽然 io 在 2.x 上也可用,但它不是 open 或 stdio 文件句柄的默认设置,这就是它在这里没有帮助的原因。