【问题标题】:Create .zip in Python?在 Python 中创建 .zip?
【发布时间】:2013-01-12 04:21:48
【问题描述】:

我试图在我的脚本中创建一个函数,它将给定源目录 (src) 的内容压缩到一个 zip 文件 (dst)。例如zip('/path/to/dir', '/path/to/file.zip'),其中/path/to/dir 是一个目录,而/path/to/file.zip 尚不存在。我不想压缩目录本身,这在我的情况下完全不同。我想压缩目录中的文件(和子目录)。这就是我正在尝试的:

def zip(src, dst):
    zf = zipfile.ZipFile("%s.zip" % (dst), "w")
    for dirname, subdirs, files in os.walk(src):
        zf.write(dirname)
        for filename in files:
            zf.write(os.path.join(dirname, filename))
    zf.close()

这会创建一个本质上是/ 的zip。例如,如果我压缩了/path/to/dir,解压缩 zip 会创建一个目录,其中包含“path”,该目录中包含“to”,等等。

有没有人不会导致这个问题的功能?

我怎么强调都不过分,它需要压缩目录中的文件,而不是目录本身。

【问题讨论】:

标签: python zip zipfile


【解决方案1】:

zipfile.write() 方法采用可选的arcname 参数 指定 zipfile 中的文件名。

您可以使用它在开头剥离src 的路径。我在这 使用os.path.abspath() 确保srcos.walk() 返回的文件名有一个共同的前缀。

#!/usr/bin/env python2.7

import os
import zipfile

def zip(src, dst):
    zf = zipfile.ZipFile("%s.zip" % (dst), "w", zipfile.ZIP_DEFLATED)
    abs_src = os.path.abspath(src)
    for dirname, subdirs, files in os.walk(src):
        for filename in files:
            absname = os.path.abspath(os.path.join(dirname, filename))
            arcname = absname[len(abs_src) + 1:]
            print 'zipping %s as %s' % (os.path.join(dirname, filename),
                                        arcname)
            zf.write(absname, arcname)
    zf.close()

zip("src", "dst")

使用这样的目录结构:

src
└── a
    ├── b
    │   └── bar
    └── foo

脚本打印:

zipping src/a/foo as a/foo
zipping src/a/b/bar as a/b/bar

生成的 zip 文件的内容是:

Archive:  dst.zip
  Length     Date   Time    Name
 --------    ----   ----    ----
        0  01-28-13 11:36   a/foo
        0  01-28-13 11:36   a/b/bar
 --------                   -------
        0                   2 files

【讨论】:

  • 看起来很有希望(编辑:完美运行),但有什么理由导入 osos.path
  • 是的—os 代表os.walk()os.path 代表os.path.abspath()os.path.join()
  • @tkbx: from os import pathpath 放在顶层,因此您可以使用path.join 而不是os.path.join。这通常不是您想要做的(尤其是因为每个人的代码中总是有一个名为 path 的变量)。
  • @tkbx: 不,你不能import sys.argv 除非argvsys 下的子模块。但是argv 不是一个模块,它只是一个list。但是当你import sys——这是你大部分时间做的正常事情——你就会做script, vars = sys.argv。 (虽然真的,你也不会经常写 that,因为如果有 0 或 2 个命令行参数,你会得到一个 ValueError。)
  • 这个函数工作正常,但它不会将空文件夹添加到 zip 文件中,这在大多数情况下是预期的行为。换句话说,任何没有文件的子文件夹都将被忽略。
【解决方案2】:

据我所知,你很接近。您可以使用dirnamebasename 来确保获取正确的路径名:

>>> os.path.dirname("/path/to/dst")
'/path/to'
>>> os.path.basename("/path/to/dst")
'dst'

然后使用chdir,您可以确保您在父级中,因此路径是相对的。

def zip(src, dst):
    parent = os.path.dirname(dst)
    folder = os.path.basename(dst)

    os.chdir(parent):
    for dirname, subdirs, filenames in os.walk(folder):
        ...

这会创建:

dst/a.txt
dst/b
dst/b/c.txt
...etc...

如果不想包含名称“dst”,您可以先输入os.chdir(dst),然后输入os.walk('.')

希望对您有所帮助。

【讨论】:

【解决方案3】:

使用arcname parameter 控制压缩文件中的名称/路径。

例如,对于仅包含文件,不包含目录的 zip 文件:

zf.write(os.path.join(dirname, filename), arcname=filename)

或者在 zip 文件中创建一个新目录:

zf.write(os.path.join(dirname, filename), arcname=os.path.join("my_zip_dir", filename))

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-10-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-21
    相关资源
    最近更新 更多