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

4 投票
3 回答
1983 浏览
提问于 2025-04-16 08:29

我正在写一个小脚本,用来把多个文件夹压缩成多个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])

我使用了数字索引,因为这样可以让脚本在处理更多文件时运行得更好。之前只写出了两个zip文件,而现在大约能生成八个,不知道为什么会这样。

这个脚本简单地遍历列表,把每个文件夹压缩成一个单独的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错误。

我的解决办法是编辑那些有问题的文件,修改它们的时间戳。也许有一天我会再看看有没有更好的解决方案。

感谢大家的帮助。

3 个回答

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

mtime 是一个时间戳,表示你的文件最后一次被修改的时间。所以,可能有某个文件的这个时间戳不太对。你需要找出是哪个文件出了问题,然后用 os.stat(filename).st_mtime 来检查一下它的修改时间。

4

关于这个问题,有个错误报告是在2007年提交的:http://bugs.python.org/issue1760357

这个问题是因为Windows的localtime函数里有个bug,时间模块除了抛出一个ValueError错误,别无他法。

我这样解决了这个问题:

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

os.utime这一行代码是用来把文件的访问时间和修改时间更新为当前时间的。

撰写回答