无法解压使用zipfile构建的归档文件(Python)
我在用Python的zipfile模块创建一个压缩文件时遇到了问题。我在一个文件夹里遍历所有文件,然后把它们写入压缩文件。可是当我尝试提取这些文件时,出现了一个和路径分隔符有关的错误。
the_path= "C:\\path\\to\\folder"
zipped= cStringIO.StringIO()
zf = zipfile.ZipFile(zipped_cache, "w", zipfile.ZIP_DEFLATED)
for dirname, subdirs, files in os.walk(the_path) :
for filename in files:
zf.write(os.path.join(dirname, filename), os.path.join(dirname[1+len(the_path):], filename))
zf.extractall("C:\\destination\\path")
zf.close()
zipped_cache.close()
这是我遇到的错误信息:
zipfile.BadZipfile: 目录中的文件名 "env\index" 和头部中的 "env/index" 不同。
更新:我把字符串缓冲区 cStringIO.StringIO()
替换成了一个临时文件 (tempfile.mkstemp("temp.zip")
),现在可以正常工作了。zipfile模块在写入缓冲区时会出现一些问题,导致压缩文件损坏,但我不太确定具体是什么问题。
问题在于我在读写文件时使用了 "r"/"w" 模式,而不是 "rb"/"wb" 模式。在Linux上这没问题,但在Windows上因为字符编码的原因就出错了。现在解决了。
4 个回答
你可以使用正斜杠(/)作为路径分隔符,即使是在Windows系统上也可以。我建议你在创建压缩文件的时候试试这个方法。
你应该在字符串前面加一个r,这样可以告诉程序这是一个原始字符串——路径中的反斜杠会被当作转义字符来处理。
下面的代码:
#!/bin/env python
print(r"C:\destination\path")
print(r"C:\path\to\folder")
print("C:\destination\path")
print("C:\path\to\folder")
会产生以下输出:
C:\destination\path
C:\path\to\folder
C:\destination\path
C:\path o
older
注意最后一行中的 \t 和 \f 被解释成了制表符和换页符。
有趣的是,你也可以把反斜杠换成正斜杠(也就是 open("C:/path/to/folder")
),这样也是可以的。
或者,你可以用反斜杠来转义反斜杠(也就是 open("C:\\path\\to\\folder")
)。
在我看来,最简单明了的办法就是直接加一个r。
编辑:
看起来你需要选择第二种方案,使用正斜杠。zipfile库似乎有点严格——而且因为这是一个仅限Windows的bug,可能是悄悄溜过来的。(参见 问题6839。)
我在这里找到了我问题的答案:http://www.penzilla.net/tutorials/python/scripting。
我把两个和压缩目录相关的函数贴出来。问题不在于字符串缓冲区,也不是斜杠,而是我在遍历和写入压缩文件时的方法。这两个递归函数解决了这个问题。用os.walk
遍历整个子目录树并不是写归档文件的好方法。
def zippy(path, archive):
paths = os.listdir(path)
for p in paths:
p = os.path.join(path, p) # Make the path relative
if os.path.isdir(p): # Recursive case
zippy(p, archive)
else:
archive.write(p) # Write the file to the zipfile
return
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!"