如何在Python中创建.zip文件?

38 投票
3 回答
55538 浏览
提问于 2025-04-17 13:58

我正在尝试在我的脚本中创建一个函数,用来把指定的源目录(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,解压后会生成一个包含“path”的目录,里面还有“to”这个目录,等等。

有没有人能提供一个不会出现这个问题的函数呢?

我想强调的是,它必须压缩目录里的文件,而不是整个目录本身。

3 个回答

1

从我了解的情况来看,你已经很接近了。你可以使用 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('.')

希望这能帮到你。

1

使用 arcname 参数 可以控制压缩文件中的文件名或路径。

比如,如果你有一个只包含文件的压缩包,没有文件夹:

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

或者你想在压缩包里新建一个文件夹:

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

zipfile.write() 方法有一个可选的参数 arcname,这个参数用来指定压缩文件内部的文件名。

你可以利用这个参数来去掉 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

而生成的压缩文件内容是:

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

撰写回答