Question

How do I zip a file in python and how do specify the compression level ?

I have the below code so far and the error I get is:

Zip("log4j.dl-service.log.2013-05-03-22",9)
AttributeError: 'str' object has no attribute 'ZipFile'

Code:

import zipfile
import fileinput

def Zip(file,level):
    """
    This function uses the zip library native to python to compress files with
    Usage: Zip(file,level)
    """

    if file and level:
        try:
            zipfile = file+'.zip'
            output = zipfile.ZipFile(zipfile, 'wb')
            for line in fileinput.input(file):
                output.write(line)
            output.close()
            if os.path.exists(zipfile):
                return zipfile
            else:
                logMe('critical',"zip failed in Zip()")
                return False

        except Exception,e:
            logMe('critical',e)
Was it helpful?

Solution

The problem here is this line:

zipfile = file+'.zip'

After that, zipfile no longer refers to the module, but to this string. So, when you do this:

output = zipfile.ZipFile(zipfile, 'wb')

You're asking a string, not a module, to call ZipFile.

Hence this error:

AttributeError: 'str' object has no attribute 'ZipFile'

The fix is to not call your variable zipfile.

As Jeff Langemeier says, the key is:

Don't use variable names that are the same as your imports that's just asking for trouble. B: Don't use variable names that are the same as your imports it makes it impossible to read. C: Don't use variable names that are the same as your imports.

More generally, don't use the same name for two different things.


For your second question:

how do specify the compression level

You can't. This is intentional, for the same reason that the zip command-line tool no longer documents 10 levels of compression, just -0 for store (no compression), and -9 for "compress better". There's almost never any good use for anything but store or the default. -9 often doesn't really compress better than the default—or it compresses some files better and others worse. If you need better compression, you need a better algorithm—e.g., use .tar.bz2 instead of .zip, or use p7zip (which can create zip-compatible files) instead of plain zip.

So, Python's library only gives you two choices: store or default. As the docs show:

class zipfile.ZipFile(file[, mode[, compression[, allowZip64]]])

compression is the ZIP compression method to use when writing the archive, and should be ZIP_STORED or ZIP_DEFLATED

And likewise for the write/writestr methods.

If you really want to do this, you can call zlib.compress directly, create a ZipInfo object directly, and add it to the archive yourself. If you look at the source (which is linked from the docs), you can see what writestr does—it's really not complicated once you strip out all the irrelevant conditions and type checks.

But really, I don't think you want to do this.

OTHER TIPS

So I guess my comment is the answer as well.

Your variables are essentially "overloading" the calls to the imported methods, making for some really bad munging of your code. So follow these rules:

A: Don't use variable names that are the same as your imports that's just asking for trouble.

B: Don't use variable names that are the same as your imports it makes it impossible to read.

C: Don't use variable names that are the same as your imports.

It'll save you and the people you ask a lot of headache if you follow this. If, you do so choose to make it close, use an underscore to separate zip_file, or filezip, or anything else.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top