Como simular ZipFile.open no Python 2.5?

Quero extrair um arquivo de um zip para um caminho específico, ignorando o caminho do arquivo no arquivo morto. Isso é muito fácil no Python 2.6 (minha documentação é maior que o código)

import shutil
import zipfile

def extract_from_zip(name, dest_path, zip_file):
    """Similar to zipfile.ZipFile.extract but extracts the file given by name
    from the zip_file (instance of zipfile.ZipFile) to the given dest_path
    *ignoring* the filename path given in the archive completely
    instead of preserving it as extract does.
    """
    dest_file = open(dest_path, 'wb')
    archived_file = zip_file.open(name)
    shutil.copyfileobj(archived_file, dest_file)


 extract_from_zip('path/to/file.dat', 'output.txt', zipfile.ZipFile('test.zip', 'r'))

Mas no Python 2.5, oZipFile.open O método não está disponível. Não consegui encontrar uma solução no stackoverflow, masesta postagem no fórum tinha uma boa solução que faz uso doZipInfo.file_offset para procurar o ponto certo no zip e usarzlib.decompressobj para descompactar os bytes de lá. InfelizmenteZipInfo.file_offset foi removido no Python 2.5!

Portanto, dado que tudo o que temos no Python 2.5 é oZipInfo.header_offset, Achei que precisaria analisar e pular a estrutura do cabeçalho para obter o deslocamento do arquivo. Usando a Wikipedia comouma referência (Eu sei) Eu vim com essa solução por muito mais tempo e não muito elegante.

import zipfile
import zlib

def extract_from_zip(name, dest_path, zip_file):
    """Python 2.5 version :("""
    dest_file = open(dest_path, 'wb')
    info = zip_file.getinfo(name)
    if info.compress_type == zipfile.ZIP_STORED:
        decoder = None
    elif info.compress_type == zipfile.ZIP_DEFLATED:
        decoder = zlib.decompressobj(-zlib.MAX_WBITS)
    else:
        raise zipfile.BadZipFile("Unrecognized compression method")

    # Seek over the fixed size fields to the "file name length" field in
    # the file header (26 bytes). Unpack this and the "extra field length"
    # field ourselves as info.extra doesn't seem to be the correct length.
    zip_file.fp.seek(info.header_offset + 26)
    file_name_len, extra_len = struct.unpack("<HH", zip_file.fp.read(4))
    zip_file.fp.seek(info.header_offset + 30 + file_name_len + extra_len)

    bytes_to_read = info.compress_size

    while True:
        buff = zip_file.fp.read(min(bytes_to_read, 102400))
        if not buff:
            break
        bytes_to_read -= len(buff)
        if decoder:
            buff = decoder.decompress(buff)
        dest_file.write(buff)

    if decoder:
        dest_file.write(decoder.decompress('Z'))
        dest_file.write(decoder.flush())

Observe como eu descompacto e leio o campo que fornece o comprimento do campo extra, porque chamarlen noZipInfo.extra O atributo fornece 4 bytes a menos, fazendo com que o deslocamento seja calculado incorretamente. Talvez esteja faltando alguma coisa aqui?

Alguém pode melhorar esta solução para o Python 2.5?

Editar: Eu deveria ter dito, a solução óbvia, como sugerido por ChrisAdams

dest_file.write(zip_file.read(name))

falhará comMemoryError para qualquer arquivo de tamanho razoável contido no zip, porque ele tenta inutilizar o arquivo inteiro na memória de uma só vez. Como tenho arquivos grandes, preciso transmitir o conteúdo para o disco.

Além disso, a atualização do Python é a solução óbvia, mas que está totalmente fora do meu alcance e é essencialmente impossível.

questionAnswers(3)

yourAnswerToTheQuestion