¿Cómo simular ZipFile.open en Python 2.5?

Quiero extraer un archivo de un zip a una ruta específica, ignorando la ruta del archivo en el archivo. Esto es muy fácil en Python 2.6 (mi cadena de documentación es más larga que el 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'))

Pero en Python 2.5, elZipFile.open El método no está disponible. No pude encontrar una solución en stackoverflow, peroesta publicación del foro tenía una buena solución que hace uso deZipInfo.file_offset para buscar el punto correcto en la cremallera y usarzlib.decompressobj para descomprimir los bytes desde allí. DesafortunadamenteZipInfo.file_offset fue eliminado en Python 2.5!

Entonces, dado que todo lo que tenemos en Python 2.5 es elZipInfo.header_offset, Pensé que solo tendría que analizar y omitir la estructura del encabezado para llegar al archivo yo mismo. Usando Wikipedia comouna referencia (Lo sé) Se me ocurrió esta solución mucho más larga y no muy 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 cómo desempaquete y lea el campo que da la longitud del campo adicional, porque al llamarlen sobre elZipInfo.extra El atributo proporciona 4 bytes menos, lo que hace que el desplazamiento se calcule incorrectamente. Tal vez me estoy perdiendo algo aquí?

¿Alguien puede mejorar esta solución para Python 2.5?

Editar: Debería haber dicho, la solución obvia como lo sugiere ChrisAdams

dest_file.write(zip_file.read(name))

fallará conMemoryError para cualquier archivo de tamaño razonable contenido en el archivo zip porque intenta extraer todo el archivo en la memoria de una sola vez. Tengo archivos grandes, así que necesito transmitir el contenido al disco.

Además, actualizar Python es la solución obvia, pero está completamente fuera de mis manos y es esencialmente imposible.

Respuestas a la pregunta(3)

Su respuesta a la pregunta