【问题标题】:How do I read a tarfile from a generator?如何从生成器中读取 tarfile?
【发布时间】:2017-01-02 12:23:14
【问题描述】:

Create a zip file from a generator in Python? 描述了一种将 .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 中解决这个问题:

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

在给定条件下如何在 Python 中做同样的事情?

【问题讨论】:

    标签: python python-2.7 generator tar bytesio


    【解决方案1】:

    我必须将生成器包装在一个构建在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)
    

    【讨论】:

    • 谢谢罗伯托!重要的是要强调你在 tarfile.open() 上使用了模式 'r|*' 而不是 'r:*',否则你会得到一个“io.UnsupportedOperation: seek”异常。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-03
    • 1970-01-01
    • 2020-06-30
    相关资源
    最近更新 更多