загрузка большого файла кусками с кодировкой gzip (Python 3.4)

Если я сделаю запрос на файл и укажу кодировку gzip, как мне это обработать?

Обычно, когда у меня есть большой файл, я делаю следующее:

while True:
   chunk = resp.read(CHUNK)
   if not chunk: break
   writer.write(chunk)
   writer.flush()

где CHUNK — это некоторый размер в байтах, Writer — это объект open(), а resp — это ответ на запрос, сгенерированный из запроса urllib.

Так что в большинстве случаев довольно просто, когда заголовок ответа содержит «gzip» в качестве возвращаемой кодировки, я бы сделал следующее:

decomp = zlib.decompressobj(16+zlib.MAX_WBITS)
data = decomp.decompress(resp.read())
writer.write(data)
writer.flush()

или это:

f = gzip.GzipFile(fileobj=buf)
writer.write(f.read())

где buf — это BytesIO().

Однако, если я попытаюсь распаковать ответ gzip, у меня возникнут проблемы:

while True:
   chunk = resp.read(CHUNK)
   if not chunk: break
   decomp = zlib.decompressobj(16+zlib.MAX_WBITS)
   data = decomp.decompress(chunk)
   writer.write(data)
   writer.flush()

Есть ли способ распаковать данные gzip, когда они поступают небольшими кусками? или мне нужно записать весь файл на диск, распаковать его, а затем переместить в окончательное имя файла? Часть проблемы, с которой я сталкиваюсь при использовании 32-битного Python, заключается в том, что я могу избавиться от ошибок памяти.

Спасибо


person code base 5000    schedule 06.01.2016    source источник


Ответы (1)


Думаю, я нашел решение, которым хочу поделиться.

def _chunk(response, size=4096):
     """ downloads a web response in pieces """
    method = response.headers.get("content-encoding")
    if method == "gzip":
        d = zlib.decompressobj(16+zlib.MAX_WBITS)
        b = response.read(size)
        while b:
            data = d.decompress(b)
            yield data
            b = response.read(size)
            del data
    else:
        while True:
            chunk = response.read(size)
            if not chunk: break
            yield chunk

Если у кого-то есть лучшее решение, пожалуйста, добавьте к нему. В основном моя ошибка заключалась в создании zlib.decompressobj(). Я создавал его не в том месте.

Кажется, это работает как в Python 2, так и в 3, так что есть плюс.

person code base 5000    schedule 06.01.2016