如何实时监控子进程产生的总输出大小?

问题描述 投票:0回答:0

下面的代码是我正在处理的实际情况的玩具示例1。 (警告:此代码将永远循环。)

import subprocess
import uuid
class CountingWriter:
    def __init__(self, filepath):
        self.file = open(filepath, mode='wb')
        self.counter = 0

    def __enter__(self):
        return self

    def __exit__(self, exc_type, exc_value, traceback):
        self.file.close()

    def __getattr__(self, attr):
        return getattr(self.file, attr)

    def write(self, data):
        written = self.file.write(data)
        self.counter += written
        return written

with CountingWriter('myoutput') as writer:
    with subprocess.Popen(['/bin/gzip', '--stdout'],
                          stdin=subprocess.PIPE,
                          stdout=writer) as gzipper:
        while writer.counter < 10000:
            gzipper.stdin.write(str(uuid.uuid4()).encode())
            gzipper.stdin.flush()
            writer.flush()
            # writer.counter remains unchanged

        gzipper.stdin.close()

在英语中,我启动了一个名为

gzipper
的子进程,它通过其
stdin
接收输入,并将压缩输出写入
CountingWriter
对象。该代码具有
while
循环,具体取决于
writer.counter
的值,在每次迭代时,将一些随机内容提供给
gzipper
.

此代码无效!

更具体地说,

writer.counter
永远不会更新,因此执行永远不会离开
while
循环。

这个例子当然是人为的,但它抓住了我想解决的问题:一旦数据写入一定数量的字节,如何终止将数据输入

gzipper

问: 我必须如何更改上面的代码才能使其正常工作?


FWIW,我认为问题与缓冲有关,因此代码中对

*.flush()
的所有调用。但是,它们没有明显的效果。顺便说一句,我不能调用
gzipper.stdout.flush()
,因为
gzipper.stdout
not
CountingWriter
对象(正如我所预期的那样),而是
None
,令人惊讶的是。


1 特别是,我使用

/bin/gzip --stdout
子进程只是为了这个例子,因为它是我实际使用的压缩程序的更容易获得的替代方案。如果我真的想
gzip
压缩我的输出,我会使用Python的标准
gzip
模块。

python subprocess ipc io-buffering
© www.soinside.com 2019 - 2024. All rights reserved.