Когда у меня есть все файлы, которые мне нужны в конкретной папке, я хотел бы, чтобы мой скрипт python заархивировал содержимое папки.
Это возможно?
И как я мог это сделать?






Вот рекурсивная версия
def zipfolder(path, relname, archive):
paths = os.listdir(path)
for p in paths:
p1 = os.path.join(path, p)
p2 = os.path.join(relname, p)
if os.path.isdir(p1):
zipfolder(p1, p2, archive)
else:
archive.write(p1, p2)
def create_zip(path, relname, archname):
archive = zipfile.ZipFile(archname, "w", zipfile.ZIP_DEFLATED)
if os.path.isdir(path):
zipfolder(path, relname, archive)
else:
archive.write(path, relname)
archive.close()
Адаптированная версия сценарий:
#!/usr/bin/env python
from __future__ import with_statement
from contextlib import closing
from zipfile import ZipFile, ZIP_DEFLATED
import os
def zipdir(basedir, archivename):
assert os.path.isdir(basedir)
with closing(ZipFile(archivename, "w", ZIP_DEFLATED)) as z:
for root, dirs, files in os.walk(basedir):
#NOTE: ignore empty directories
for fn in files:
absfn = os.path.join(root, fn)
zfn = absfn[len(basedir)+len(os.sep):] #XXX: relative path
z.write(absfn, zfn)
if __name__ == '__main__':
import sys
basedir = sys.argv[1]
archivename = sys.argv[2]
zipdir(basedir, archivename)
Пример:
C:\zipdir> python -mzipdir c:\tmp\test test.zip
Создает архив 'C:\zipdir\test.zip' с содержимым каталога 'c:\tmp\test'.
zfn = absfn[len(basedir)+len(os.sep):] почему не absbasedir=os.path.abspath(basedir); os.path.relpath(absfn,absbasedir)? Также длина baseir и os.sep может рассматриваться как постоянная, поэтому она должна быть вне двух циклов for.
никогда раньше не слышал о contextlib.closing, но он делает оператор с обратно совместимым с 2,5. Раньше я сталкивался с ошибкой с ... «with [оператор] из будущего»;), потому что некоторые функции stdlib не поддерживали с в 2,5 (даже если сам оператор работал с импортом), хотя поддерживал его в 2,7. Думаю, этого можно было бы избежать с помощью closing.
Я использовал это решение, но мне пришлось изменить следующую строку: zfn = absfn [len (basedir) + len (os.sep):] и вычесть единицу в позицию следующим образом: zfn = absfn [len (basedir) + len (os. sep) -1:] иначе в имени файла пропущена буква
@jfosoriot 1 - это код Python 2.5. Вместо этого попробуйте shutil.make_archive. 2- нормализовать, заканчивается ли basedir разделителем пути (косая черта): if len(basedir) > 1: basedir = basedir.rstrip(os.sep)
В python 2.7 вы можете использовать: shutil.make_archive (base_name, format [, root_dir [, base_dir [, verbose [, dry_run [, owner [, group [, logger]]]]]]]).
base_name имя архива без расширения
формат формат архива
root_dir каталог для сжатия.
Например
shutil.make_archive(target_file, format = "bztar", root_dir=compress_me)
ответ для современного Python - здесь