#python #compression #gzip
Вопрос:
Я пытаюсь взять существующий csv-файл на небольшой виртуальной машине Windows 10 объемом около 17 ГБ и сжать его с помощью gzip. Он слишком велик, чтобы его можно было прочитать в памяти.
Ищу способы сделать это эффективно, не требующие разбиения файла на разделы.
Это то, что я пытаюсь сделать прямо сейчас, и это довольно медленно:
import gzip
import shutil
with open('file_to_be_compressed.csv', 'rb') as f_in:
with gzip.open('test_out.csv.gz', 'wb') as f_out:
shutil.copyfileobj(f_in, f_out)
Редактировать:
Это часть конвейера, в котором я загружаю данные из одного источника и загружаю их в другой. Загрузка будет намного быстрее, если я смогу сначала сжать файлы (к сожалению, они еще не были сжаты на стороне источника).
Итак, у меня есть код, который извлекает список файлов, и для каждого файла я хотел бы сжать его, а затем загрузить.
Комментарии:
1. Какая операционная система? Вы хотите сохранить исходный файл? Обычно это делается с помощью внешней утилиты.
gzip thefile.csv
сжал быthefile.csv.gz
и удалил оригинал.2. Мне не нужно хранить исходный файл. Я добавил правку, чтобы уточнить. Мне просто нужно, чтобы эти файлы были меньше, чтобы обеспечить более быструю загрузку в облачное хранилище.
3. Вы сжимаете 17 гигабайт с помощью gzip, используя максимальный уровень сжатия. Основываясь на различных критериях, вы можете ожидать скорость сжатия около 10 Мбит/с, поэтому общее время сжатия файла может составлять около получаса. Уменьшите уровень сжатия-снижение до уровня 6 приведет к незначительному ухудшению степени сжатия, и это будет в 2-3 раза быстрее.
4. Вы можете использовать подпроцесс для внешнего вызова gzip. Это будет быстрее, чем прохождение кода на python. Хотя, скорее всего, немного быстрее. Сжатие занимает время.
5. @tdelaney Я сомневаюсь, что это что-то изменит, узким местом обязательно будет GZip, а не Python или IO. Я даже протестировал его локально, разница между запуском скрипта Python и простым использованием gzip в командной строке с одинаковым уровнем сжатия составляет около 0,2 секунды.
Ответ №1:
Если я правильно понимаю, вы загружаете большой файл .csv, в идеале вы хотели бы сжать его на лету и загрузить сжатую версию.
Если это правильно, то вам не нужно записывать ни несжатые, ни сжатые данные в файлы. Вместо этого вы можете загружать фрагмент за раз, сжимать по ходу и загружать сжатые данные.
Для этого используйте zlib. Создайте zlib.compressobj()
объект со wbits
значением 31
, равным , чтобы выбрать формат gzip. Допустим, вы называете этот объект gz
. Затем используйте gz.compress(data)
для каждого фрагмента .csv, который вы загружаете. Загрузите результат, возвращенный каждым gz.compress(data)
. Когда загрузка будет завершена, загрузите результат gz.flush()
, чтобы завершить сжатые данные.