第一个问题是readlines https://docs.python.org/2.7/library/stdtypes.html#file.readlines将所有行读入列表中。在所有行都存在之前它无法做到这一点,直到stdin
已达到 EOF。
但你实际上并不需要list的行,只是一些可迭代的的线条。还有一个文件,比如sys.stdin
, 已经is这样一个可迭代的。而且它是一种懒惰的方式,只要一行可用,就一次生成一行,而不是等待一次生成所有行。
So:
for line in sys.stdin:
print line
每当你发现自己伸手去够readlines
,问问自己是否真的需要它。答案将always不。 (嗯,除非你想用参数调用它,或者在一些有缺陷的、不完全像文件的对象上调用它。)参见阅读线被认为是愚蠢的 http://stupidpythonideas.blogspot.com/2013/06/readlines-considered-silly.html了解更多。
但与此同时,有一个second问题。这并不是说Python正在缓冲它的stdin
,或者其他进程正在缓冲其stdout
,但是文件对象迭代器本身正在进行内部缓冲,这可能(取决于您的平台 - 但在大多数 POSIX 平台上,通常会)阻止您到达第一行,直到 EOF,或者至少直到很多行已被读取。
This is a known problem with Python 2.x, which has been fixed in 3.x,* but that doesn't help you unless you're willing to upgrade.
该解决方案在命令行和环境文档以及大多数系统的联机帮助页中都有提及,但隐藏在-u标记文档 https://docs.python.org/2/using/cmdline.html#cmdoption-u:
请注意,xreadlines()、readlines() 和文件对象迭代器(“for line in sys.stdin”)中有内部缓冲,不受此选项的影响。要解决此问题,您需要在“while 1:”循环中使用“sys.stdin.readline()”。
换句话说:
while True:
line = sys.stdin.readline()
if not line:
break
print line
Or:
for line in iter(sys.stdin.readline, ''):
print line
对于不同的问题,在这个答案 https://stackoverflow.com/questions/3670323/setting-smaller-buffer-size-for-sys-stdin/3670470#3670470,Alex Martelli 指出你总是可以忽略sys.stdin
and re-fdopen
文件描述符。这意味着您将获得 POSIX fd 的包装器,而不是 C stdio 句柄。但这对于this问题,因为问题不在于 C stdio 缓冲,而在于file.__iter__
缓冲与其相互作用。
* Python 3.x doesn't use the C stdio library's buffering anymore; it does everything itself, in the types in the io https://docs.python.org/3/library/io.html module, which means the iterator can just share the same buffer the file object itself is using. While io
is available on 2.x as well, it's not the default thing you get for open
—or for the stdio file handles, which is why it doesn't help here.