【问题标题】:Can't unzip archive built with zipfile (Python)无法解压缩使用 zipfile (Python) 构建的存档
【发布时间】:2011-08-29 03:59:09
【问题描述】:

我在使用 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”和标题 “环境/索引”不同。

更新:我用一个临时文件 (tempfile.mkstemp("temp.zip")) 替换了字符串缓冲区 cStringIO.StringIO(),现在它可以工作了。当 zipfile 模块写入损坏存档的缓冲区时会发生一些事情,但不确定是什么问题。

问题是我正在从/写入以“r”/​​“w”模式而不是“rb”/“wb”模式打开的文件中的信息。这在 Linux 中不是问题,但由于字符编码,它在 Windows 中给了我错误。解决了。​​

【问题讨论】:

  • 我仅将这些作为示例,路径格式正确,带有转义的反斜杠('C:\\path\\to\\folder')。但是,没有一个答复回答了这个问题。例外是“zipfile.BadZipfile:目录“env\index”和标题“env/index”中的文件名不同。”
  • +1 支持反对随机的、无法解释的反对票。
  • 我更新了我的答案——这应该可以解决你的问题。
  • 如果你使用zf.write(os.path.join(dirname, filename))会发生什么?
  • 好吧,如果我不给write 函数提供第二个参数,它只会在存档中构建整个目录结构,而我不需要。例如。 useless\\directory\\structure\\up\\to\\relevant\\directory 而不是 relevant\\directory。我认为这个问题与cStringIO.StringIO() 有关

标签: python zip archive zipfile


【解决方案1】:

您应该考虑在字符串前添加 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 在最后一行被解释为 tabformfeed

有趣的是,您还可以将反斜杠更改为正斜杠(即open("C:/path/to/folder"),这样会起作用。

或者,使用 ... 反斜杠(即open("C:\\path\\to\\folder"))转义反斜杠。

IMO,最清晰和最简单的解决方案是简单地添加一个 r


编辑: 看起来您需要使用第二种解决方案,正斜杠。 zipfile 库显然有点严格——鉴于这是一个仅限窗口的错误,它可能会偷偷溜进来。 (见Issue 6839)。

【讨论】:

    【解决方案2】:

    在这里找到我的问题的答案:http://www.penzilla.net/tutorials/python/scripting

    我正在粘贴与压缩目录相关的两个函数。问题不是字符串缓冲区,也不是斜杠,而是我迭代和写入 zipfile 的方式。这两个递归函数解决了这个问题。使用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!"
    

    【讨论】:

      【解决方案3】:

      您需要转义路径中的反斜杠。

      尝试更改以下内容:

      • the_path= "C:\path\to\folder"the_path = "C:\\path\\to\\folder",以及
      • zf.extractall("C:\destination\path")zf.extractall("C:\\destination\\path")

      【讨论】:

        【解决方案4】:

        即使在 Windows 上,您也可以使用正斜杠作为路径分隔符。我建议您在创建 zip 文件时尝试一下。

        【讨论】:

          猜你喜欢
          • 2019-02-05
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2010-10-13
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多