在 Python 中创建 .zip?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14568647/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-18 11:50:49  来源:igfitidea点击:

Create .zip in Python?

pythonzipzipfile

提问by tkbx

I'm trying to create a function in my script that zips the contents of a given source directory (src) to a zip file (dst). For example, zip('/path/to/dir', '/path/to/file.zip'), where /path/to/diris a directory, and /path/to/file.zipdoesn't exist yet. I do notwant to zip the directory itself, this makes all the difference in my case. I want to zip the files (and subdirs) in the directory. This is what I'm trying:

我正在尝试在我的脚本中创建一个函数,将给定源目录 ( src) 的内容压缩到一个 zip 文件 ( dst)。例如,zip('/path/to/dir', '/path/to/file.zip'), where/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()

This creates a zip that is essentially /. For example, if I zipped /path/to/dir, extracting the zip creates a directory with "path" in it, with "to" in that directory, etc.

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

Does anyone have a function that doesn't cause this problem?

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

I can't stress this enough, it needsto zip the files in the directory, not the directoy itself.

我不能强调这一点,它需要压缩目录中的文件,而不是目录本身。

采纳答案by andrewdotn

The zipfile.write()method takes an optional arcnameargument that specifies what the name of the file should be inside the zipfile.

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

You can use this to strip off the path to srcat the beginning. Here I use os.path.abspath()to make sure that both srcand the filename returned by os.walk()have a common prefix.

您可以使用它来去除src开头的路径。这里我os.path.abspath()用来确保两者src和返回的文件名os.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")

With a directory structure like this:

使用这样的目录结构:

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

The script prints:

脚本打印:

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

And the contents of the resulting zip file are:

生成的 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

回答by agoebel

From what I can tell you are close. You could use dirnameand basenameto make sure you are grabbing the right path name:

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

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

Then using chdiryou can make sure you are in the parent so the paths are relative.

然后使用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):
        ...

This creates:

这会产生:

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

If do not want to include the name "dst" you can just do os.chdir(dst)and then os.walk('.').

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

Hope that helps.

希望有帮助。

回答by Jon-Eric

Use the arcnameparameterto control the name/path in the zip file.

使用该arcname参数来控制 zip 文件中的名称/路径。

For example, for a zip file that contains only files, no directories:

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

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

Or to invent a new directory inside the zip file:

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

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