下面的代码是我正在处理的实际情况的玩具示例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
模块。