python
July 11, 2021

Сжатие и разбиение файлов с Python

Данные операции решают проблемы перемещения файлов большого размера на удаленный сервер и обратно. Быстро разберемся с ними и автоматизируем процесс, чтобы избежать лишних расходов драгоценного времени.

Для последующих манипуляций будем использовать модуль zipfile.

Создание архива

Для этого потребуется создать экземпляр класса ZipFile и вызвать его метод write с указанием пути к файлу, который помещается в архив. Напишем простой блок кода, который архивирует заданную папку:

import zipfile
import os
dir_source = 'source'
arch_fn = 'data'
with zipfile.ZipFile(f'{arch_fn}.zip', 'w') as zip_f:
   for folder, subfolders, filenames in os.walk(dir_source):
       for filename in filenames:
           zip_f.write(os.path.join(folder, filename))

Получение информации об архиве

Опять же сначала потребуется создать экземпляр класса ZipFile. Список названий входящих в архив файлов можно получить, обратившись к методу namelist, а размеры файлов и их сжатых копий из свойств объекта информации о содержимом (file_size, compress_size), получаемого через метод getinfo. Продемонстрируем вывод информации о содержимом архива на примере:

zip_f = zipfile.ZipFile(f'{arch_fn}.zip')
for fn in zip_f.namelist():
    info = zip_f.getinfo(fn)
    print(f'файл - {fn}, размер - {info.file_size}, сжатый размер - {info.compress_size}')

Извлечение файлов из архива

Для этого создается экземпляр класса ZipFile и вызывается его метод extract или extractall для извлечения конкретного или всех файлов. При этом в обоих можно указать путь к папке, иначе копирование происходит в рабочий каталог. Вот как полностью извлечь архив в заданную папку:

dir_out = 'output'
zip_f = zipfile.ZipFile(f'{arch_fn}.zip')
zip_f.extractall(dir_out)

Дальнейшие операции происходят с использованием модуля filesplit. Для работы потребуется создать экземпляр класса Filesplit:

from fsplit.filesplit import Filesplit
fs = Filesplit()

Разбиение

Затем разбиение производится методом split с указанием файла, размера части в байтах, выходной директории (если не указана, то текущая) и, возможно, callback функции, вызываемой после формирования каждой части:

dir_pieces = 'pieces'
if not os.path.exists(dir_pieces):
    os.mkdir(dir_pieces)
def split_cb(f, s):
    print("file: {0}, size: {1}".format(f, s))

fs.split(file=f'{arch_fn}.zip', split_size=50000, output_dir=dir_pieces, callback=split_cb)

Объединение

Данная операция выполняется методом merge объекта класса Filesplit:

def merge_cb(f, s):
    print("file: {0}, size: {1}".format(f, s))

fs.merge(input_dir=f'{arch_fn}.zip', callback=merge_cb)

Обязательный параметр только путь к папке с набором частей, также по выбору можно задать выходной файл (либо будет создан в той же папке, где и части) и callback функцию: