Python中的ZipFile模块 - 运行时问题

4

我正在编写一个小脚本,用于按照特定结构将多个文件夹压缩成多个zip文件。我已经将结构构建为列表。以下是一些条目:

['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']

下面是负责将文件压缩在一起的两种方法。
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

主要的脚本部分如下所示:
for i in range(len(myList)):
    zipit(myList[i],os.path.split(myList[i])[1])

我使用数字索引是因为这使得脚本在更多的文件上运行良好。在那之前,只有2个zip文件被写入。这样,大约有8个文件完成了压缩。不知道为什么。

该脚本简单地遍历列表并将每个列表项压缩为单独的zip文件。当列表的大小更大时,问题就会发生。我收到以下错误消息。

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')

有人知道是什么原因导致了这个错误吗? 谢谢!
编辑: 我已经使用下面提供的代码来测试文件,问题出在一些文件的“最后修改”时间戳上。由于某种未知的原因,其中一些文件的最后修改时间在2049年。 在这种情况下,Python zipfile模块在压缩文件时失败,并抛出ValueError异常。 我的解决方案:编辑有问题的文件以更改它们的时间戳。也许有一天我会验证是否有更好的解决方案。 感谢大家的帮助。

1
你能否在zipfile.py中加入一个打印语句,将st.st_mtime的值打印出来,就在这个调用的上面? - Martin v. Löwis
1
受影响的文件的修改时间是什么? - Ignacio Vazquez-Abrams
3个回答

4

这个问题相关的错误报告已经在2007年提交:http://bugs.python.org/issue1760357

这个问题是由于Windows localtime函数中的一个bug引起的,time模块除了抛出ValueError之外无法做任何事情。

我是这样解决这个问题的:

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

os.utime这一行会将文件的访问时间和修改时间更新为当前时间。

0

看看这个是否更好。至少,您将了解哪个文件失败以及原因。

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', '.')

我尝试了你的代码,但在一个时间戳为2098年的文件中出现了错误。我认为这导致了溢出,因此出现了错误。现在我将尝试使用像7Zip这样的程序压缩此文件并查看发生了什么。顺便说一句,你的算法让我检测到了错误,但是在压缩文件夹时,它不会在zip文件内保留文件夹结构。 - Thiago Moraes

0

mtime 是文件上次修改的时间戳。因此,对于一个文件来说,它可能以某种方式无效。找出导致这种情况的文件,然后调用 os.stat(filename).st_mtime 进行检查。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接