我陷入了将一个脚本的输出传递到另一个脚本(两个都是python)的问题.
这个问题非常相似,但(1)它没有提供答案(2)我的情况略有不同.所以,我认为开一个新问题会更好.
这是问题所在.
两个脚本几乎完全相同:
receiver.py
import sys
import time
for line in sys.stdin:
sys.stdout.write(line)
sys.stdout.flush()
time.sleep(3)
Run Code Online (Sandbox Code Playgroud)
replicator.py
import sys
import time
for line in sys.stdin:
sys.stderr.write(line)
sys.stderr.flush()
time.sleep(3)
Run Code Online (Sandbox Code Playgroud)
当我一个接一个地在bash或cmd中执行这些脚本时,一切都很好.以下两个示例都正常工作,我在输出中看到输入文本:
作品:(每3秒输出一行输出)
cat data.txt | python receiver.py
cat data.txt | python replicator.py
Run Code Online (Sandbox Code Playgroud)
但是一旦我从一个脚本管道到另一个脚本,它们就会停止工作:
不起作用:(在到达文件末尾之前没有任何内容出现)
cat data.txt | python receiver.py | python replicator.py
Run Code Online (Sandbox Code Playgroud)
然后,当我将第一个脚本传递给另一个工具时,它再次工作!
作品:
cat data.txt | python receiver.py | cat -n
cat data.txt | python replicator.py | cat -n
Run Code Online (Sandbox Code Playgroud)
最后,当我删除阻塞sleep()函数时,它再次开始工作:
删除计时器:
time.sleep(0)
Run Code Online (Sandbox Code Playgroud)
它现在有效:
cat data.txt | python receiver.py | python replicator.py
Run Code Online (Sandbox Code Playgroud)
有人知道我的管道有什么问题吗?我不是在寻找替代方法.我只想了解这里发生的事情.
根据评论,我改进了这些例子.
现在这两个脚本不仅打印出内容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)
Run Code Online (Sandbox Code Playgroud)
data.txt中
Line-A
Line-B
Line-C
Line-D
Run Code Online (Sandbox Code Playgroud)
结果
$> 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
Run Code Online (Sandbox Code Playgroud)
正如您所看到的那样,当我将python脚本的输出传递给它自己时,第二个脚本会一直等到第一个脚本完成.然后它开始消化数据.
但是,当我使用其他工具(sed在此示例中)时,该工具会立即接收数据.为什么会这样?
这是由于文件对象( )中的内部缓冲造成的。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)
Run Code Online (Sandbox Code Playgroud)
该代码将按预期工作:
$ 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
Run Code Online (Sandbox Code Playgroud)
...请注意,file.readlines() 和文件对象(对于 sys.stdin 中的行)中有内部缓冲,不受此选项的影响。要解决此问题,您需要在 while 1: 循环内使用 file.readline() 。
注意:这个问题在Python 3File Object中已修复
| 归档时间: |
|
| 查看次数: |
2291 次 |
| 最近记录: |