Conseguido!!

A partir de esta información: http://stackoverflow.com/questions/297345/create-a-zip-file-from-a-generator-in-python/2734156#2734156

He creado esta implementación, os la dejo por si alguno le interesara:


import time, shutil
from zipfile import ZipFile, ZipInfo, ZIP_DEFLATED
import zlib, binascii, struct

class ZipWriter(object):
    def __init__(self, zf, filename):
        self.zf = zf
        self.filename = filename
        self.zinfo = self._ZipInfo(filename)
        self.file_size = 0
        self.compress_size = 0
        self.CRC = 0

        if self.zinfo.compress_type == ZIP_DEFLATED:
self.cmpr = zlib.compressobj(zlib.Z_DEFAULT_COMPRESSION, zlib.DEFLATED, -15)
        else:
            self.cmpr = None

    def _ZipInfo(self, filename):
        zinfo = ZipInfo(filename=filename,
                            date_time=time.localtime(time.time())[:6])
        zinfo.compress_type = self.zf.compression
        zinfo.external_attr = 0600 << 16
        zinfo.file_size = 0
        zinfo.flag_bits = 0x00
        zinfo.CRC = 0
        zinfo.compress_size = 0

        zinfo.header_offset = self.zf.fp.tell()    # Start of header bytes

        self.zf._writecheck(zinfo)
        self.zf._didModify = True

        self.zf.fp.write(zinfo.FileHeader())

        return zinfo

    def write(self, bytes):
        self.file_size = self.file_size + len(bytes)
        self.CRC = binascii.crc32(bytes, self.CRC)
        if self.cmpr:
            bytes = self.cmpr.compress(bytes)
            self.compress_size = self.compress_size + len(bytes)

        self.zf.fp.write(bytes)

    def close(self):
        if self.cmpr:
            buf = cmpr.flush()
            self.compress_size = self.compress_size + len(buf)
            self.zf.fp.write(buf)
            self.zinfo.compress_size = self.compress_size
        else:
            self.zinfo.compress_size = self.file_size

        self.zinfo.CRC = self.CRC
        self.zinfo.file_size = self.file_size

        position = self.zf.fp.tell()
        self.zf.fp.seek(self.zinfo.header_offset + 14, 0)
self.zf.fp.write(struct.pack("<lLL", self.zinfo.CRC, self.zinfo.compress_size, self.zinfo.file_size))
        self.zf.fp.seek(position, 0)
        self.zf.filelist.append(self.zinfo)
        self.zf.NameToInfo[self.zinfo.filename] = self.zinfo

def copyZipFile(source, target):
    zsource = ZipFile(source, "r")
    ztarget = ZipFile(target, "w")

    for item in zsource.infolist():
        fsrc = zsource.open(item.filename, "r")
        fdst = ZipWriter(ztarget, item.filename)
        shutil.copyfileobj(fsrc, fdst)
        fdst.close()
        fsrc.close()

    zsource.close()
    ztarget.close()



Saludos

Juande







El 24/01/2011 23:29, Juan de Dios Manjón Pérez escribió:
Andrey,

también he llegado al punto que comentas,
el problema que tengo ahora es para escribir el chuck, ya que ZipFile.open(name, mode='r', pwd=None) no admite mode='w'.

El unico metodo ZipFile.writestr(zinfo_or_arcname, bytes) que he encontrado para escribir requiere que se escriba TODO de golpe.

La implementación que busco es parecida a:

from zipfile import ZipFile
from shutil import copyfileobj

def copyZipFile(source, target):
    zsource = ZipFile(source,"r")
    ztarget = ZipFile(target,"w")

    for item in zsource.infolist():
        fsrc = zsource.open(item.filename,"r")
fdst = ztarget.open(item.filename,"w") #mode no acepta "w". exception
        copyfileobj(fsrc,fdst)
        fdst.close()
        fsrc.close()

    zsource.close()
    ztarget.close()


Saludos

Juande



El 24/01/2011 20:14, Andrey Antoukh escribió:
http://docs.python.org/py3k/library/zipfile.html

ZipFile.open(name, mode='r', pwd=None)
Extract a member from the archive as a file-like object (ZipExtFile). name is the name of the file in the archive, or a ZipInfo object. The mode parameter, if included, must be one of the following: 'r' (the default), 'U', or 'rU'. Choosing 'U' or 'rU' will enable universal newline support in the read-only object. pwd is the password used for encrypted files. Calling open() on a closed ZipFile will raise a RuntimeError.

Note The file-like object is read-only and provides the following methods: read(), readline(), readlines(), __iter__(), __next__().

Lo que a groso modo quiere decir que devuelve un objeto fichero que tiene todos los métodos estándares para leer. De lo que se deduce que podemos leerlos a cachitos para que no ocupe memoria.

La implementación seria parecida a la que ya se ha propuesto. O como el simple ejemplo...

>>> zipobj = zipfile.ZipFile("prueba.zip", "r")
>>> for zip in zipobj.namelist():
...     zipfileobj = zipobj.open(zip, "r")
...     for chuck in zipfileobj:
...         # lo que sea que tengas que hacer con estos datos.

Un saludo.


_______________________________________________
Python-es mailing list
[email protected]
http://mail.python.org/mailman/listinfo/python-es
FAQ: http://python-es-faq.wikidot.com/

_______________________________________________
Python-es mailing list
[email protected]
http://mail.python.org/mailman/listinfo/python-es
FAQ: http://python-es-faq.wikidot.com/

Responder a