Как я могу создать zip-архив структуры каталогов в Python?
Как создать zip-архив каталога?
Ответы (26)
Как указывали другие, вы должны использовать zipfile. В документации рассказывается, какие функции доступны, но не объясняется, как их можно использовать для заархивирования всего каталога. Я думаю, что проще всего объяснить пример кода:
import os
import zipfile
def zipdir(path, ziph):
# ziph is zipfile handle
for root, dirs, files in os.walk(path):
for file in files:
ziph.write(os.path.join(root, file),
os.path.relpath(os.path.join(root, file),
os.path.join(path, '..')))
zipf = zipfile.ZipFile('Python.zip', 'w', zipfile.ZIP_DEFLATED)
zipdir('tmp/', zipf)
zipf.close()
os.path.relpath(os.path.join(root, file), os.path.join(path, '..'))
. Это позволит вам заархивировать каталог из любого рабочего каталога без получения полных абсолютных путей в архиве.
- person Reimund; 29.06.2013
shutil
делает это очень просто, используя всего одну строку. Пожалуйста, проверьте ответ ниже ..
- person droidlabour; 30.05.2017
.close()
!
- person information_interchange; 23.01.2018
file
не является ключевым словом, даже если ваш редактор выделяет его как одно.
- person Eric; 02.11.2018
with zipfile.ZipFile('Python.zip', 'w', zipfile.ZIP_DEFLATED) as zipf: zipdir('tmp/', zipfh)
- person AndB; 11.11.2020
ziph
в этой функции? path
- это каталог. Что делать, если у меня есть каталог, содержащий другие подкаталоги? Я добавил вопрос, связанный с этим. stackoverflow.com/questions/67119676/
- person icatalan; 16.04.2021
shutil
.
- person José L. Patiño; 11.07.2021
zipfile.ZipFile('Python.meta_zip', 'w')
В моей работе мы должны сгруппировать каталог метаданных с файлами в нем и файлом, с которым они связаны. Нам не нужно сжатие, мы просто хотим, чтобы все они были в одном месте, когда мы загружаем их в облако.
- person Tanner Davis; 14.07.2021
Самый простой способ - использовать shutil.make_archive
. Он поддерживает форматы zip и tar.
import shutil
shutil.make_archive(output_filename, 'zip', dir_name)
Если вам нужно сделать что-то более сложное, чем заархивировать весь каталог (например, пропустить определенные файлы), вам нужно будет покопаться в _ 3_, как предлагали другие.
shutil
является частью стандартной библиотеки Python. Это должен быть главный ответ
- person AlexG; 28.04.2017
shutil.make_archive
использует os.chdir()
. Судя по тому, что я читаю о os.chdir()
, он действует глобально.
- person Sam Malayek; 25.07.2018
base_dir
вариант
- person mckbrd; 26.06.2020
os.chdir
, который может привести к заархивированию неправильного каталога. Это привело к тому, что мои zip-архивы стали гигантскими, а на диске закончилось место.
- person xjcl; 01.03.2021
Чтобы добавить содержимое mydirectory
в новый zip-файл, включая все файлы и подкаталоги:
import os
import zipfile
zf = zipfile.ZipFile("myzipfile.zip", "w")
for dirname, subdirs, files in os.walk("mydirectory"):
zf.write(dirname)
for filename in files:
zf.write(os.path.join(dirname, filename))
zf.close()
with
вместо того, чтобы в конце позвонить самому себе close()
?
- person ArtOfWarfare; 12.01.2018
Как я могу создать zip-архив структуры каталогов в Python?
В скрипте Python
В Python 2.7+ shutil
имеет функцию make_archive
.
from shutil import make_archive
make_archive(
'zipfile_name',
'zip', # the archive format - or tar, bztar, gztar
root_dir=None, # root for archive - current working dir if None
base_dir=None) # start archiving from here - cwd if None too
Здесь заархивированный архив будет называться zipfile_name.zip
. Если base_dir
находится дальше от root_dir
, он исключает файлы не в base_dir
, но по-прежнему архивирует файлы в родительских каталогах до root_dir
.
У меня была проблема с тестированием этого на Cygwin с 2.7 - ему нужен аргумент root_dir для cwd:
make_archive('zipfile_name', 'zip', root_dir='.')
Использование Python из оболочки
Вы можете сделать это с помощью Python из оболочки, также используя модуль zipfile
:
$ python -m zipfile -c zipname sourcedir
Где zipname
- это имя файла назначения, который вы хотите (добавьте .zip
, если хотите, он не сделает это автоматически), а sourcedir - это путь к каталогу.
Архивирование Python (или просто не нужен родительский каталог):
Если вы пытаетесь заархивировать пакет python с __init__.py
и __main__.py
, и вам не нужен родительский каталог, это
$ python -m zipfile -c zipname sourcedir/*
А также
$ python zipname
запустит пакет. (Обратите внимание, что вы не можете запускать подпакеты в качестве точки входа из заархивированного архива.)
Архивирование приложения Python:
Если у вас установлен python3.5 + и вы хотите заархивировать пакет Python, используйте zipapp < / а>:
$ python -m zipapp myapp
$ python myapp.pyz
Эта функция будет рекурсивно архивировать дерево каталогов, сжимая файлы и записывая правильные относительные имена файлов в архив. Записи в архиве такие же, как созданные zip -r output.zip source_dir
.
import os
import zipfile
def make_zipfile(output_filename, source_dir):
relroot = os.path.abspath(os.path.join(source_dir, os.pardir))
with zipfile.ZipFile(output_filename, "w", zipfile.ZIP_DEFLATED) as zip:
for root, dirs, files in os.walk(source_dir):
# add directory (needed for empty dirs)
zip.write(root, os.path.relpath(root, relroot))
for file in files:
filename = os.path.join(root, file)
if os.path.isfile(filename): # regular files only
arcname = os.path.join(os.path.relpath(root, relroot), file)
zip.write(filename, arcname)
Используйте shutil, который является частью стандартной библиотеки Python. Использовать shutil очень просто (см. Код ниже):
- 1-й аргумент: имя результирующего файла zip / tar,
- 2-й аргумент: zip / tar,
- 3-й аргумент: dir_name
Код:
import shutil
shutil.make_archive('/home/user/Desktop/Filename','zip','/home/username/Desktop/Directory')
Современный Python (3.6+), использующий модуль pathlib
для краткой ООП-подобной обработки пути и pathlib.Path.rglob()
для рекурсивного подстановки. Насколько я могу судить, это эквивалентно ответу Джорджа В. Рейли: zip-архивы со сжатием, самый верхний элемент - это каталог, хранит пустые каталоги, использует относительные пути.
from pathlib import Path
from zipfile import ZIP_DEFLATED, ZipFile
from os import PathLike
from typing import Union
def zip_dir(zip_name: str, source_dir: Union[str, PathLike]):
src_path = Path(source_dir).expanduser().resolve(strict=True)
with ZipFile(zip_name, 'w', ZIP_DEFLATED) as zf:
for file in src_path.rglob('*'):
zf.write(file, file.relative_to(src_path.parent))
Примечание: как указывают необязательные подсказки типа, zip_name
не может быть объектом Path (будет исправлено в версии 3.6.2 + а>).
Чтобы добавить сжатие к полученному zip-файлу, ознакомьтесь с эту ссылку.
Вам нужно изменить:
zip = zipfile.ZipFile('Python.zip', 'w')
to
zip = zipfile.ZipFile('Python.zip', 'w', zipfile.ZIP_DEFLATED)
Я внес некоторые изменения в код, предоставленный Марком Байерсом. Функция ниже также добавит пустые каталоги, если они у вас есть. Примеры должны прояснить, какой путь добавлен в zip.
#!/usr/bin/env python
import os
import zipfile
def addDirToZip(zipHandle, path, basePath=""):
"""
Adding directory given by \a path to opened zip file \a zipHandle
@param basePath path that will be removed from \a path when adding to archive
Examples:
# add whole "dir" to "test.zip" (when you open "test.zip" you will see only "dir")
zipHandle = zipfile.ZipFile('test.zip', 'w')
addDirToZip(zipHandle, 'dir')
zipHandle.close()
# add contents of "dir" to "test.zip" (when you open "test.zip" you will see only it's contents)
zipHandle = zipfile.ZipFile('test.zip', 'w')
addDirToZip(zipHandle, 'dir', 'dir')
zipHandle.close()
# add contents of "dir/subdir" to "test.zip" (when you open "test.zip" you will see only contents of "subdir")
zipHandle = zipfile.ZipFile('test.zip', 'w')
addDirToZip(zipHandle, 'dir/subdir', 'dir/subdir')
zipHandle.close()
# add whole "dir/subdir" to "test.zip" (when you open "test.zip" you will see only "subdir")
zipHandle = zipfile.ZipFile('test.zip', 'w')
addDirToZip(zipHandle, 'dir/subdir', 'dir')
zipHandle.close()
# add whole "dir/subdir" with full path to "test.zip" (when you open "test.zip" you will see only "dir" and inside it only "subdir")
zipHandle = zipfile.ZipFile('test.zip', 'w')
addDirToZip(zipHandle, 'dir/subdir')
zipHandle.close()
# add whole "dir" and "otherDir" (with full path) to "test.zip" (when you open "test.zip" you will see only "dir" and "otherDir")
zipHandle = zipfile.ZipFile('test.zip', 'w')
addDirToZip(zipHandle, 'dir')
addDirToZip(zipHandle, 'otherDir')
zipHandle.close()
"""
basePath = basePath.rstrip("\\/") + ""
basePath = basePath.rstrip("\\/")
for root, dirs, files in os.walk(path):
# add dir itself (needed for empty dirs
zipHandle.write(os.path.join(root, "."))
# add files
for file in files:
filePath = os.path.join(root, file)
inZipPath = filePath.replace(basePath, "", 1).lstrip("\\/")
#print filePath + " , " + inZipPath
zipHandle.write(filePath, inZipPath)
Выше представлена простая функция, которая должна работать в простых случаях. Вы можете найти более элегантный класс в моем Gist: https://gist.github.com/Eccenux/17526123107ca0ac28e6 < / а>
У меня есть еще один пример кода, который может помочь, используя python3, pathlib и zipfile. Он должен работать в любой ОС.
from pathlib import Path
import zipfile
from datetime import datetime
DATE_FORMAT = '%y%m%d'
def date_str():
"""returns the today string year, month, day"""
return '{}'.format(datetime.now().strftime(DATE_FORMAT))
def zip_name(path):
"""returns the zip filename as string"""
cur_dir = Path(path).resolve()
parent_dir = cur_dir.parents[0]
zip_filename = '{}/{}_{}.zip'.format(parent_dir, cur_dir.name, date_str())
p_zip = Path(zip_filename)
n = 1
while p_zip.exists():
zip_filename = ('{}/{}_{}_{}.zip'.format(parent_dir, cur_dir.name,
date_str(), n))
p_zip = Path(zip_filename)
n += 1
return zip_filename
def all_files(path):
"""iterator returns all files and folders from path as absolute path string
"""
for child in Path(path).iterdir():
yield str(child)
if child.is_dir():
for grand_child in all_files(str(child)):
yield str(Path(grand_child))
def zip_dir(path):
"""generate a zip"""
zip_filename = zip_name(path)
zip_file = zipfile.ZipFile(zip_filename, 'w')
print('create:', zip_filename)
for file in all_files(path):
print('adding... ', file)
zip_file.write(file)
zip_file.close()
if __name__ == '__main__':
zip_dir('.')
print('end!')
Для краткого способа сохранить иерархию папок в родительском каталоге для архивации:
import glob
import zipfile
with zipfile.ZipFile(fp_zip, "w", zipfile.ZIP_DEFLATED) as zipf:
for fp in glob(os.path.join(parent, "**/*")):
base = os.path.commonpath([parent, fp])
zipf.write(fp, arcname=fp.replace(base, ""))
Если хотите, вы можете изменить это, чтобы использовать pathlib
для подстановки файлов.
Вы, вероятно, захотите взглянуть на модуль zipfile
; есть документация на http://docs.python.org/library/zipfile.html .
Вы также можете захотеть os.walk()
для индексации структуры каталогов.
Вот вариант ответа Nux, который подходит мне:
def WriteDirectoryToZipFile( zipHandle, srcPath, zipLocalPath = "", zipOperation = zipfile.ZIP_DEFLATED ):
basePath = os.path.split( srcPath )[ 0 ]
for root, dirs, files in os.walk( srcPath ):
p = os.path.join( zipLocalPath, root [ ( len( basePath ) + 1 ) : ] )
# add dir
zipHandle.write( root, p, zipOperation )
# add files
for f in files:
filePath = os.path.join( root, f )
fileInZipPath = os.path.join( p, f )
zipHandle.write( filePath, fileInZipPath, zipOperation )
Попробуйте следующее. У меня сработало.
import zipfile, os
zipf = "compress.zip"
def main():
directory = r"Filepath"
toZip(directory)
def toZip(directory):
zippedHelp = zipfile.ZipFile(zipf, "w", compression=zipfile.ZIP_DEFLATED )
list = os.listdir(directory)
for file_list in list:
file_name = os.path.join(directory,file_list)
if os.path.isfile(file_name):
print file_name
zippedHelp.write(file_name)
else:
addFolderToZip(zippedHelp,file_list,directory)
print "---------------Directory Found-----------------------"
zippedHelp.close()
def addFolderToZip(zippedHelp,folder,directory):
path=os.path.join(directory,folder)
print path
file_list=os.listdir(path)
for file_name in file_list:
file_path=os.path.join(path,file_name)
if os.path.isfile(file_path):
zippedHelp.write(file_path)
elif os.path.isdir(file_name):
print "------------------sub directory found--------------------"
addFolderToZip(zippedHelp,file_name,path)
if __name__=="__main__":
main()
Если вам нужна такая функциональность, как папка сжатия любого обычного графического файлового менеджера, вы можете использовать следующий код, он использует zipfile. Используя этот код, у вас будет zip-файл с путем в качестве его корневой папки.
import os
import zipfile
def zipdir(path, ziph):
# Iterate all the directories and files
for root, dirs, files in os.walk(path):
# Create a prefix variable with the folder structure inside the path folder.
# So if a file is at the path directory will be at the root directory of the zip file
# so the prefix will be empty. If the file belongs to a containing folder of path folder
# then the prefix will be that folder.
if root.replace(path,'') == '':
prefix = ''
else:
# Keep the folder structure after the path folder, append a '/' at the end
# and remome the first character, if it is a '/' in order to have a path like
# folder1/folder2/file.txt
prefix = root.replace(path, '') + '/'
if (prefix[0] == '/'):
prefix = prefix[1:]
for filename in files:
actual_file_path = root + '/' + filename
zipped_file_path = prefix + filename
zipf.write( actual_file_path, zipped_file_path)
zipf = zipfile.ZipFile('Python.zip', 'w', zipfile.ZIP_DEFLATED)
zipdir('/tmp/justtest/', zipf)
zipf.close()
Для большей гибкости, например выберите каталог / файл по имени используйте:
import os
import zipfile
def zipall(ob, path, rel=""):
basename = os.path.basename(path)
if os.path.isdir(path):
if rel == "":
rel = basename
ob.write(path, os.path.join(rel))
for root, dirs, files in os.walk(path):
for d in dirs:
zipall(ob, os.path.join(root, d), os.path.join(rel, d))
for f in files:
ob.write(os.path.join(root, f), os.path.join(rel, f))
break
elif os.path.isfile(path):
ob.write(path, os.path.join(rel, basename))
else:
pass
Для файлового дерева:
.
├── dir
│ ├── dir2
│ │ └── file2.txt
│ ├── dir3
│ │ └── file3.txt
│ └── file.txt
├── dir4
│ ├── dir5
│ └── file4.txt
├── listdir.zip
├── main.py
├── root.txt
└── selective.zip
Вы можете, например, выберите только dir4
и root.txt
:
cwd = os.getcwd()
files = [os.path.join(cwd, f) for f in ['dir4', 'root.txt']]
with zipfile.ZipFile("selective.zip", "w" ) as myzip:
for f in files:
zipall(myzip, f)
Или просто listdir
в каталог вызова скрипта и добавьте все оттуда:
with zipfile.ZipFile("listdir.zip", "w" ) as myzip:
for f in os.listdir():
if f == "listdir.zip":
# Creating a listdir.zip in the same directory
# will include listdir.zip inside itself, beware of this
continue
zipall(myzip, f)
Допустим, вы хотите заархивировать все папки (подкаталоги) в текущем каталоге.
for root, dirs, files in os.walk("."):
for sub_dir in dirs:
zip_you_want = sub_dir+".zip"
zip_process = zipfile.ZipFile(zip_you_want, "w", zipfile.ZIP_DEFLATED)
zip_process.write(file_you_want_to_include)
zip_process.close()
print("Successfully zipped directory: {sub_dir}".format(sub_dir=sub_dir))
Здесь так много ответов, и я надеюсь, что смогу внести свой вклад в свою собственную версию, основанную на исходном ответе (кстати), но с более графической перспективой, также использующей контекст для каждой zipfile
настройки и сортировки os.walk()
, чтобы иметь упорядоченный вывод.
Имея эти папки и их файлы (среди других папок), я хотел создать .zip
для каждой cap_
папки:
$ tree -d
.
├── cap_01
| ├── 0101000001.json
| ├── 0101000002.json
| ├── 0101000003.json
|
├── cap_02
| ├── 0201000001.json
| ├── 0201000002.json
| ├── 0201001003.json
|
├── cap_03
| ├── 0301000001.json
| ├── 0301000002.json
| ├── 0301000003.json
|
├── docs
| ├── map.txt
| ├── main_data.xml
|
├── core_files
├── core_master
├── core_slave
Вот что я применил, с комментариями для лучшего понимания процесса.
$ cat zip_cap_dirs.py
""" Zip 'cap_*' directories. """
import os
import zipfile as zf
for root, dirs, files in sorted(os.walk('.')):
if 'cap_' in root:
print(f"Compressing: {root}")
# Defining .zip name, according to Capítulo.
cap_dir_zip = '{}.zip'.format(root)
# Opening zipfile context for current root dir.
with zf.ZipFile(cap_dir_zip, 'w', zf.ZIP_DEFLATED) as new_zip:
# Iterating over os.walk list of files for the current root dir.
for f in files:
# Defining relative path to files from current root dir.
f_path = os.path.join(root, f)
# Writing the file on the .zip file of the context
new_zip.write(f_path)
По сути, для каждой итерации над os.walk(path)
я открываю контекст для установки zipfile
, а затем повторяю итерацию по files
, который представляет собой list
файлов из каталога root
, формируя относительный путь для каждого файла на основе текущего каталога root
, добавляя в запущенный zipfile
контекст.
И результат представлен так:
$ python3 zip_cap_dirs.py
Compressing: ./cap_01
Compressing: ./cap_02
Compressing: ./cap_03
Чтобы увидеть содержимое каждого .zip
каталога, вы можете использовать команду less
:
$ less cap_01.zip
Archive: cap_01.zip
Length Method Size Cmpr Date Time CRC-32 Name
-------- ------ ------- ---- ---------- ----- -------- ----
22017 Defl:N 2471 89% 2019-09-05 08:05 7a3b5ec6 cap_01/0101000001.json
21998 Defl:N 2471 89% 2019-09-05 08:05 155bece7 cap_01/0101000002.json
23236 Defl:N 2573 89% 2019-09-05 08:05 55fced20 cap_01/0101000003.json
-------- ------- --- -------
67251 7515 89% 3 files
Заархивируйте файл или дерево (каталог и его подкаталоги).
from pathlib import Path
from zipfile import ZipFile, ZIP_DEFLATED
def make_zip(tree_path, zip_path, mode='w', skip_empty_dir=False):
with ZipFile(zip_path, mode=mode, compression=ZIP_DEFLATED) as zf:
paths = [Path(tree_path)]
while paths:
p = paths.pop()
if p.is_dir():
paths.extend(p.iterdir())
if skip_empty_dir:
continue
zf.write(p)
Чтобы добавить к существующему архиву, передайте mode='a'
, чтобы создать новый архив mode='w'
(значение по умолчанию в приведенном выше). Допустим, вы хотите связать 3 разных дерева каталогов в одном архиве.
make_zip(path_to_tree1, path_to_arch, mode='w')
make_zip(path_to_tree2, path_to_arch, mode='a')
make_zip(path_to_file3, path_to_arch, mode='a')
Решение с использованием pathlib.Path
, которое не зависит от используемой ОС:
import zipfile
from pathlib import Path
def zip_dir(path: Path, zip_file_path: Path):
"""Zip all contents of path to zip_file"""
files_to_zip = [
file for file in path.glob('*') if file.is_file()]
with zipfile.ZipFile(
zip_file_path, 'w', zipfile.ZIP_DEFLATED) as zip_f:
for file in files_to_zip:
print(file.name)
zip_f.write(file, file.name)
current_dir = Path.cwd()
zip_dir = current_dir / "test"
tools.zip_dir(
zip_dir, current_dir / 'Zipped_dir.zip')
Вот современный подход с использованием pathlib и диспетчера контекста. Помещает файлы непосредственно в zip-архив, а не во вложенную папку.
def zip_dir(filename: str, dir_to_zip: pathlib.Path):
with zipfile.ZipFile(filename, 'w', zipfile.ZIP_DEFLATED) as zipf:
# Use glob instead of iterdir(), to cover all subdirectories.
for directory in dir_to_zip.glob('**'):
for file in directory.iterdir():
if not file.is_file():
continue
# Strip the first component, so we don't create an uneeded subdirectory
# containing everything.
zip_path = pathlib.Path(*file.parts[1:])
# Use a string, since zipfile doesn't support pathlib directly.
zipf.write(str(file), str(zip_path))
Я подготовил функцию, объединив решение Марка Байерса с комментариями Реймунда и Мортена Зилмеров (относительный путь и включая пустые каталоги). Рекомендуется использовать with
при создании файла ZipFile.
Функция также подготавливает имя zip-файла по умолчанию с именем заархивированного каталога и расширением .zip. Следовательно, он работает только с одним аргументом: исходный каталог, который нужно заархивировать.
import os
import zipfile
def zip_dir(path_dir, path_file_zip=''):
if not path_file_zip:
path_file_zip = os.path.join(
os.path.dirname(path_dir), os.path.basename(path_dir)+'.zip')
with zipfile.ZipFile(path_file_zip, 'wb', zipfile.ZIP_DEFLATED) as zip_file:
for root, dirs, files in os.walk(path_dir):
for file_or_dir in files + dirs:
zip_file.write(
os.path.join(root, file_or_dir),
os.path.relpath(os.path.join(root, file_or_dir),
os.path.join(path_dir, os.path.pardir)))
Что ж, после прочтения предложений я придумал очень похожий способ, который работает с 2.7.x без создания "забавных" имен каталогов (абсолютные имена), и создаст только указанную папку внутри zip.
Или на всякий случай, если вам нужно, чтобы ваш zip-архив содержал внутри папку с содержимым выбранного каталога.
def zipDir( path, ziph ) :
"""
Inserts directory (path) into zipfile instance (ziph)
"""
for root, dirs, files in os.walk( path ) :
for file in files :
ziph.write( os.path.join( root, file ) , os.path.basename( os.path.normpath( path ) ) + "\\" + file )
def makeZip( pathToFolder ) :
"""
Creates a zip file with the specified folder
"""
zipf = zipfile.ZipFile( pathToFolder + 'file.zip', 'w', zipfile.ZIP_DEFLATED )
zipDir( pathToFolder, zipf )
zipf.close()
print( "Zip file saved to: " + pathToFolder)
makeZip( "c:\\path\\to\\folder\\to\\insert\\into\\zipfile" )
Функция для создания zip-файла.
def CREATEZIPFILE(zipname, path):
#function to create a zip file
#Parameters: zipname - name of the zip file; path - name of folder/file to be put in zip file
zipf = zipfile.ZipFile(zipname, 'w', zipfile.ZIP_DEFLATED)
zipf.setpassword(b"password") #if you want to set password to zipfile
#checks if the path is file or directory
if os.path.isdir(path):
for files in os.listdir(path):
zipf.write(os.path.join(path, files), files)
elif os.path.isfile(path):
zipf.write(os.path.join(path), path)
zipf.close()
Для всех, кто углубляется в этот вопрос и пытается заархивировать тот же каталог, в котором находится их программа, и получает как очень глубокие древовидные структуры, так и заканчивает рекурсией из-за самого zip-файла, попробуйте это.
Это комбинация ответа Марка и некоторых дополнительных проверок, чтобы убедиться, что нет рекурсивного архивирования самого zip-файла и нет излишне глубоких структуры папок.
import os
import zipfile
def zipdir(path, ziph, ignored_directories, ignored_files):
# ziph is zipfile handle
for root, dirs, files in os.walk(path):
for file in files:
if not any(ignored_dir in root for ignored_dir in ignored_directories):
if not any(ignored_fname in file for ignored_fname in ignored_files):
ziph.write(os.path.join(root, file))
# current working directory
this_dir = os.path.dirname(os.path.abspath(__file__))
# the directory within the working directory the zip will be created in (build/archives).
zip_dest_dir = os.path.join('build', 'archives')
# verify zip_dest_dir exists: if not, create it
if not os.path.isdir(zip_dest_dir):
os.makedirs(zip_dest_dir, exist_ok=True)
# leave zip_dest_dir blank (or set dist_dir = this_dir) if you want the zip file in the working directory (same directory as the script)
dest_dir = os.path.join(this_dir, zip_dest_dir)
# name the zip file: remember the file extension
zip_filename = 'zipped_directory.zip'
# zip file's path
zip_path = os.path.join(dest_dir, zip_filename)
# create the zipfile handle: you can change ZIP_STORED to any other compression algorithm of your choice, like ZIP_DEFLATED, if you need actual compression
zipf = zipfile.ZipFile(zip_path, 'w', zipfile.ZIP_STORED)
# ignored files and directories: I personally wanted to ignore the "build" directory, alongside with "node_modules", so those would be listed here.
ignored_dirs = []
# ignore any specific files: in my case, I was ignoring the script itself, so I'd include 'deploy.py' here
ignored_files = [zip_filename]
# zip directory contents
zipdir('.', zipf, ignored_dirs, ignored_files)
zipf.close()
Результирующий zip-файл должен включать только каталоги, начинающиеся с рабочего каталога: поэтому нет Users / user / Desktop / code /.../ working_directory /.../ и т. Д. вид файловой структуры.
Очевидным способом было бы пойти с shutil, как сказано во втором верхнем ответе, но если вы по какой-то причине все еще хотите использовать ZipFile, и если у вас возникают проблемы с этим (например, ERR 13 в Windows и т. Д.) , Вы можете использовать это исправление:
import os
import zipfile
def retrieve_file_paths(dirName):
filePaths = []
for root, directories, files in os.walk(dirName):
for filename in files:
filePath = os.path.join(root, filename)
filePaths.append(filePath)
return filePaths
def main(dir_name, output_filename):
filePaths = retrieve_file_paths(dir_name)
zip_file = zipfile.ZipFile(output_filename+'.zip', 'w')
with zip_file:
for file in filePaths:
zip_file.write(file)
main("my_dir", "my_dir_archived")
Этот рекурсивно выполняет итерацию по каждой подпапке / файлу в данной папке и записывает их в zip-файл вместо попытки напрямую заархивировать папку.
make_archive
изshutil
(если вы хотите рекурсивно заархивировать один каталог). - person malana   schedule 09.10.2018