如何从生成器读取tar文件?

7

如何在Python中使用生成器创建zip文件?提供了一种从一组文件将.zip写入磁盘的解决方案。

我面临着相反的问题。我已经得到了一个生成器:

stream = attachment.iter_bytes()
print type(stream)

我希望能将其导入到类似于tar gunzip文件的对象中:

b = io.BytesIO(stream)
f = tarfile.open(mode='r:gz', fileobj = b)
f.list()

但是我不会:
<type 'generator'>
Error: 'generator' does not have the buffer interface

我可以在shell中这样解决:

我可以通过如下shell命令来解决:

$ curl --options http://URL | tar zxf - ./path/to/interesting_file

在给定的条件下,我该如何使用Python实现相同的功能?

1个回答

4

我不得不将生成器包装在一个基于io模块构建的类文件对象中。

def generator_to_stream(generator, buffer_size=io.DEFAULT_BUFFER_SIZE):
    class GeneratorStream(io.RawIOBase):
        def __init__(self):
            self.leftover = None

        def readable(self):
            return True

        def readinto(self, b):
            try:
                l = len(b)  # : We're supposed to return at most this much
                chunk = self.leftover or next(generator)
                output, self.leftover = chunk[:l], chunk[l:]
                b[:len(output)] = output
                return len(output)
            except StopIteration:
                return 0  # : Indicate EOF
    return io.BufferedReader(GeneratorStream())

使用此方法,您可以打开tar文件并提取其内容。

stream = generator_to_stream(any_stream)
tar_file = tarfile.open(fileobj=stream, mode='r|*')
#: Do whatever you want with the tar_file now

for member in tar_file:
    member_file = tar_file.extractfile(member)

1
感谢Roberto!需要强调的是,您在tarfile.open()中使用了模式'r|*'而不是'r:*',否则您将会得到一个“io.UnsupportedOperation: seek”异常。 - Martin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接