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

Posted

技术标签:

【中文标题】Python 中的 ZipFile 模块 - 运行时问题【英文标题】:ZipFile module in Python - Runtime problems 【发布时间】:2010-12-13 23:47:32 【问题描述】:

我正在编写一个小脚本,以按照一定的结构将多个文件夹压缩到多个 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 个 zipfile。这样,大约 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。

我的解决方案:编辑有问题的文件以更改其时间戳。也许有一天我会验证是否有更好的解决方案。

感谢大家的帮助。

【问题讨论】:

你能在 zipfile.py 中加入一个打印语句,在这个调用的正上方打印出 st.st_mtime 的值吗? 什么受影响文件的mtime? 【参考方案1】:

2007 年提交了与此问题相关的错误报告:http://bugs.python.org/issue1760357

此问题是由 Windows localtime 函数中的错误引起的,时间模块除了抛出 ValueError 之外无能为力。

我解决了这样的问题:

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

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

【讨论】:

【参考方案2】:

mtime 是您的文件上次修改时间的时间戳。因此,对于一个文件,它可能在某种程度上是无效的。找出是什么文件引起的,然后打电话给os.stat(filename).st_mtime检查。

【讨论】:

【参考方案3】:

看看这是否更好。至少,您会发现哪个文件失败以及失败的原因。

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 之类的程序压缩这个文件,看看会发生什么。顺便说一句,你的算法让我检测到错误,但是在压缩文件夹时,它不会在 zipfile 中保留文件夹结构。

以上是关于Python 中的 ZipFile 模块 - 运行时问题的主要内容,如果未能解决你的问题,请参考以下文章

python中的zipfile?

如何使用 Python 的 zipfile 模块对 ZIP 文件中的文件设置权限(属性)?

python zipfile 是线程安全的吗?

ZipFile 模块创建 .pyc 文件

Python的zipfile模块无法更新条目[重复]

Python zipfile 模块不压缩文件