【问题标题】:Pipe output of one iteration of a python for loop to another scriptpython for循环的一次迭代的输出到另一个脚本
【发布时间】:2017-11-30 17:18:56
【问题描述】:

for 循环的每个实例都会吐出一个二进制文件的内容,该二进制文件应由另一个脚本捕获以进行进一步处理。例如:

script1.py

filename = glob.glob('*.txt')
for i in range(len(filename)):
    with open(filename[i], 'rb') as g:
        sys.stdout.write(g.read())

script2.py

from subprocess import call
script = "cat > test.fil"
call(script,shell=True) 

命令:

python script1.py | python script2.py

如果我执行此命令,它会等待所有迭代完成,然后再将输出传送到 script2.py。我希望这可以分批完成。例如,将一个二进制文件中的数据推送到标准输出后,启动 script2.py。

script2.py 不能从 script1.py 调用。这两个脚本都需要在不同的 docker 容器中运行。最好避免在 docker 容器内安装 docker。

【问题讨论】:

  • 为什么不直接在第二个脚本中读取stdin 而不是尝试使用shell 来做呢? (你可以用 shell 来做,虽然你还没有把它连接到stdin,但我认为这是我见过的最多的useless use of cat。)
  • script2.py 将看到相同的连续字节流,无论script1.py 如何写入它们。如果没有一些额外的字节注入到script1.py 的输出中并从中解析,您将无法可靠地区分来自不同文件的字节。
  • @chepner,你能给我举个例子吗?
  • @kindall 你说得对,我可以直接使用标准输入而不是使用 cat,但我希望 script2 能够可靠地区分不同的文件,就像 chepner 所指出的那样。你知道这是怎么做到的吗?
  • 有两个选项:如果您知道一个字符串是否不能出现在任何输入文件中,您可以简单地将其写入文件之间的输出流。否则,一个更安全的想法是将文件大小写入流before文件,这样消费者就知道在读取一个文件大小之后,接下来的X字节都是同一个文件的一部分。读取那么多字节后,下一个输入应该是另一个文件大小。基本上,您需要某种协议来将多个文件编码到一个流中,script1.pyscript2.py 都会同意。

标签: python python-2.7 shell docker pipe


【解决方案1】:

如果sys.stdout 连接到管道,默认情况下它会缓冲。您必须调用 sys.stdout.flush() 来刷新输出:

sys.stdout.write(g.read())
sys.stdout.flush()

您的第二个脚本也可以直接读取标准输入,而不是调用 shell 来调用 cat 来读取它。按照您的编写方式,您正在执行 3 个进程(python、您的 shell、cat)。

import shutil
import sys
with open('test.fil', 'w') as f:
    shutil.copyfileobj(sys.stdin, f)

在不相关的注释中,您不需要在数字 range 中使用 for 循环,因为您打算仅使用数字来索引 listfor 循环可以直接在 list 元素中迭代:

filenames = glob.glob('*.txt')
for filename in filenames:
    with open(filename, 'rb') as g:
        ...

【讨论】:

  • 如果文件小于管道缓冲区,flush 唯一会做的是强制输出。它不会帮助第二个脚本识别来自一个特定文件的字节。
  • @nosklo 你说得对,我不需要使用 cat,但是 script2 有没有办法像 chepner 提到的那样可靠地区分不同的文件。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-05-10
  • 2011-07-11
  • 2010-12-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多