如何将一个python脚本的输出传递给另一个python脚本

时间:2017-07-10 14:52:49

标签: python

我陷入了将一个脚本的输出传递到另一个脚本(两个都是python)的问题。

question非常相似,但(1)它没有提供答案(2)我的情况略有不同。所以,我认为开一个新问题会更好。

这是问题所在 两个脚本几乎完全相同:

receiver.py

import sys
import time

for line in sys.stdin:
    sys.stdout.write(line)
    sys.stdout.flush()
    time.sleep(3)

replicator.py

import sys
import time

for line in sys.stdin:
    sys.stderr.write(line)
    sys.stderr.flush()
    time.sleep(3)

当我一个接一个地在 bash cmd 中执行这些脚本时,一切都很好。以下两个示例都正常工作,我在输出中看到输入文本:

作品(每3秒钟会出现一行输出)

cat data.txt | python receiver.py
cat data.txt | python replicator.py

但是一旦我从一个脚本管道到另一个脚本,他们就会停止工作:

不能工作(在到达文件末尾之前不会显示任何内容)

cat data.txt | python receiver.py | python replicator.py

然后,当我将第一个脚本传递给另一个工具时,它再次工作!

使用:

cat data.txt | python receiver.py | cat -n
cat data.txt | python replicator.py | cat -n

最后,当我删除阻塞sleep()函数时,它再次开始工作:

删除计时器:

time.sleep(0)

现在可行:

cat data.txt | python receiver.py | python replicator.py

有人知道我的滚边有什么问题吗? 我不是在寻找替代方法。我只是想了解这里发生了什么。

更新

根据评论,我对例子进行了改进 现在,这两个脚本不仅打印出data.txt的内容,还为每一行添加时间戳。

receiver.py

import sys
import time
import datetime

for line in sys.stdin:
    sys.stdout.write(str(datetime.datetime.now().strftime("%H:%M:%S"))+'\t')
    sys.stdout.write(line)
    sys.stdout.flush()
    time.sleep(1)

data.txt中

Line-A
Line-B
Line-C
Line-D

结果

$> cat data.txt
Line-A
Line-B
Line-C
Line-D

$> cat data.txt | python receiver.py
09:05:44        Line-A
09:05:45        Line-B
09:05:46        Line-C
09:05:47        Line-D

$> cat data.txt | python receiver.py | python receiver.py
09:05:54        09:05:50        Line-A
09:05:55        09:05:51        Line-B
09:05:56        09:05:52        Line-C
09:05:57        09:05:53        Line-D

$> cat test.log | python receiver.py | sed -e "s/^/$(date +"%H:%M:%S") /"
09:17:55        09:17:55        Line-A
09:17:55        09:17:56        Line-B
09:17:55        09:17:57        Line-C
09:17:55        09:17:58        Line-D

$> cat test.log | python receiver.py | cat | python receiver.py
09:36:21        09:36:17        Line-A
09:36:22        09:36:18        Line-B
09:36:23        09:36:19        Line-C
09:36:24        09:36:20        Line-D

正如您所看到的,当我将python脚本的输出传递给它自己时,第二个脚本会一直等到第一个脚本完成。然后它开始消化数据。

但是,当我使用其他工具(在此示例中为sed)时,该工具会立即接收数据。为什么会这样?

1 个答案:

答案 0 :(得分:1)

这是由于文件对象for line in sys.stdin)中的内部缓冲

因此,如果我们逐行获取

import sys
import time
import datetime

while True:
    line = sys.stdin.readline()
    if not line:
       break
    sys.stdout.write(str(datetime.datetime.now().strftime("%H:%M:%S"))+'\t')
    sys.stdout.write(line)
    sys.stdout.flush()
    time.sleep(1)

代码将按预期工作:

$ cat data.txt | python receiver.py |  python receiver.py
09:43:46        09:43:46        Line-A
09:43:47        09:43:47        Line-B
09:43:48        09:43:48        Line-C
09:43:49        09:43:49        Line-D

Documentation

  

...请注意,file.readlines()和File中有内部缓冲   对象( for sys.stdin 中的行)不受此影响   选项。要解决此问题,您将需要使用file.readline()   在一段时间内1:循环。

注意:在Python 3

中修复了File Object内容