pythonzip

overwriting file in ziparchive


I have archive.zip with two files: hello.txt and world.txt

I want to overwrite hello.txt file with new one with that code:

import zipfile

z = zipfile.ZipFile('archive.zip','a')
z.write('hello.txt')
z.close()  

but it won't overwrite file, somehow it creates another instance of hello.txt — take a look at winzip screenshot:

alt text

Since there is no smth like zipfile.remove(), what's the best way to handle this problem?


Solution

  • There's no way to do that with python zipfile module. You have to create a new zip file and recompress everything again from the first file, plus the new modified file.

    Below is some code to do just that. But note that it isn't efficient, since it decompresses and then recompresses all data.

    import tempfile
    import zipfile
    import shutil
    import os
    
    def remove_from_zip(zipfname, *filenames):
        tempdir = tempfile.mkdtemp()
        try:
            tempname = os.path.join(tempdir, 'new.zip')
            with zipfile.ZipFile(zipfname, 'r') as zipread:
                with zipfile.ZipFile(tempname, 'w') as zipwrite:
                    for item in zipread.infolist():
                        if item.filename not in filenames:
                            data = zipread.read(item.filename)
                            zipwrite.writestr(item, data)
            shutil.move(tempname, zipfname)
        finally:
            shutil.rmtree(tempdir)
    

    Usage:

    remove_from_zip('archive.zip', 'hello.txt')
    with zipfile.ZipFile('archive.zip', 'a') as z:
        z.write('hello.txt')