Thiago Moraes
Thiago Moraes

Reputation: 617

ZipFile module in Python - Runtime problems

I'm doing a little script to zip multiple folders in multiple zip files following a certain structure. I've built the structure as a list. Here are some entries:

['E:\Documents\UFSCar\Primeiro Ano\Primeiro Semestre\Cálculo 1',
'E:\Documents\UFSCar\Primeiro Ano\Segundo Semestre\Estatistica',
'E:\Documents\UFSCar\Primeiro Ano\Segundo Semestre\Estruturas Discretas',
'E:\Documents\UFSCar\Primeiro Ano\Segundo Semestre\Introdução à Engenharia']

Down here are the 2 methods resposible for zipping the files together.

def zipit (path, archname):
    # Create a ZipFile Object primed to write
    archive = ZipFile(archname, "w", ZIP_DEFLATED) # "a" to append, "r" to read
    # Recurse or not, depending on what path is
    if os.path.isdir(path):
        zippy(path, archive)
    else:
        archive.write(path)
    archive.close()
    return "Compression of \""+path+"\" was successful!"

def zippy(path,archive):
    paths = os.listdir(path)
    for p in paths:
        p = os.path.join(path,p)
        if os.path.isdir(p):
            zippy(p,archive)
        else:
            archive.write(p)
    return

The main part os the script is like this:

for i in range(len(myList)):
    zipit(myList[i],os.path.split(myList[i])[1])

I've used numerical indexes because this made the script run well for a larger number of files. Before that, only 2 zipfiles we're written. This way, about 8 make its way to the end. No clue why.

The script simply iterates over the list and compresses each one as a separated zipfile. The problem happens when the size of the list is bigger. I get the following error message.

Traceback (most recent call last):
  File "E:\Documents\UFSCar\zipit.py", line 76, in <module>
    zipit(listaDisciplinas[i],os.path.split(listaDisciplinas[i])[1])
  File "E:\Documents\UFSCar\zipit.py", line 22, in zipit
    zippy(path, archive)
  File "E:\Documents\UFSCar\zipit.py", line 11, in zippy
    zippy(p,archive)
  File "E:\Documents\UFSCar\zipit.py", line 11, in zippy
    zippy(p,archive)
  File "E:\Documents\UFSCar\zipit.py", line 13, in zippy
    archive.write(p)
  File "C:\Python27\lib\zipfile.py", line 994, in write
    mtime = time.localtime(st.st_mtime)
ValueError: (22, 'Invalid argument')

Do anyone knows what may cause this error? thanks!

EDIT:

I've used the code provided below to teste the files, the problem were the files with problems with their "last modified" timestamp. For some reason unknown, some of them had the the last modification in the 2049 year.

In that case, the Python zipfile module failed in compressing the files as a ValueError was thrown.

My solution: edit the problematic files to chance their timestamp. Maybe someday I verify is there is a better solution.

Thanks for the help of everyone.

Upvotes: 4

Views: 2164

Answers (3)

Philip
Philip

Reputation: 470

A bug report related to this issue was submitted in 2007: http://bugs.python.org/issue1760357

The problem is caused by a bug in the Windows localtime function and there's nothing the time module can do other than throw a ValueError.

I got around the problem like this:

try:
    zip.write(absfilename, zipfilename)
except ValueError:
    os.utime(absfilename, None)
    zip.write(absfilename, zipfilename)

The os.utime line update the file's access and modified times to the current time.

Upvotes: 4

hughdbrown
hughdbrown

Reputation: 49033

See if this works any better. At a minimum, you'll find out which file is failing and why.

import os
import os.path
from time import localtime
from zipfile import ZipFile, ZIP_DEFLATED

def zipper(zipfilename, directory):
    archive = ZipFile(zipfilename, "w", ZIP_DEFLATED)
    for root, dirs, files in os.walk(directory):
        for f in files:
            path = os.path.join(root, f)
            try:
                archive.write(path)
            except ValueError, err:
                print "Error compressing %s" % path
                s = os.stat(path)
                print s.st_mtime
                print localtime(s.st_mtime)
                print str(err)
    archive.close()

if __name__ == '__main__':
    zipper('foo.zip', '.')

Upvotes: 0

Thomas K
Thomas K

Reputation: 40390

mtime is a timestamp for when your file was last modified. So, it's probably invalid in some way for one file. Work out what file causes it, then call os.stat(filename).st_mtime to check it.

Upvotes: 0

Related Questions