急切地从stdin Python返回行

时间:2015-12-18 15:20:48

标签: python stdin

我正在创建一个脚本,其中包含一些其他脚本输出管道。另一个脚本需要一段时间才能完成,并将进度与我要解析的数据一起打印到控制台上。

由于我将结果传递给我的脚本,我希望能够做两件事。随着我的输入,我想在屏幕上回应它。命令完成后,我希望有一个通过stdin传递的行列表。

我的第一个是使用简单的

for line in sys.stdin:
     sys.stdout.write(line + '\n')
     lines.append(line)
     sys.stdout.flush()

但令我惊讶的是,命令等待直到stdin命中EOF,直到它开始产生线条。

我目前的解决方法是:

line = sys.stdin.readline()
lines = []
while line:
    sys.stdout.write(line.strip() + '\n')
    lines.append(line.strip())
    sys.stdout.flush()
    line = sys.stdin.readline()

但是这并不总是等到使用整个输入。

还有其他办法吗? for解决方案的行为方式似乎很奇怪。

2 个答案:

答案 0 :(得分:1)

其他人已经告诉过你有关无缓冲输出的信息。我只想补充一些想法:

  1. 通常最好将调试信息打印到stderr,stderr输出通常是无缓冲的
  2. 将中间输出委托给特殊工具更简单。例如,有一个tee实用程序,它允许拆分前一个命令的stdout。假设您在bash,您可以立即将中间输出打印到stdout,并使用process substitution而不是打印到文件(而不是awk,您将调用您的python脚本):

    $ python -c 'for i in range(5): print i+1' | tee >( awk '{print "from awk", $0**2 }')
    1
    2
    3
    4
    5
    from awk 1
    from awk 4
    from awk 9
    from awk 16
    from awk 25
    

答案 1 :(得分:0)

你需要在你的python程序中创建1)stdin和2)在管道的相反一侧的stdout都是行缓冲的。为了得到这个 1)在你的程序中使用stdin = os.fdopen(sys.stdin.fileno(), 'r', 1); 2)使用stdbuf -oL更改其他程序输出的缓冲模式:

stdbuf -oL otherprogram | python yourscript.py