null

Создаем tar.gz с несколькими csv с помощью Python

Доброго времени суток друзья. В этой заметке хочу поделиться с вами опытом написания кода на питоне, генерирующим архив с двумя CSV файлами. Чтобы сделать архив в питоне есть модуль 'tarfile'. Начнём с простого давайте попробуем создать архив и положить в него 2 существующих файла:

import tarfile
with tarfile.open('/path/to/new/tar_file/', mode='w:gz') as tar: 
    tar.add('/path/to/first_file', 'name_in_archive_1')         
    tar.add('/path/to/second_file', 'name_in_archive_2')
tar.close()   

В этом примере мы создаем архив из двух уже существующих файлов. При вызове функции open, мы указываем помимо стандартного для открытия файлов режима w - write, параметр 'gz'. ​​​​​​​Это позволит автоматически сжать полученный архив с помощью gzip. Если вам необходимо настроить уровень сжатия (comperssion level), то просто добавьте дополнительный параметр compresslevel в функцию open. Этот параметр может принимать значения от 1 до 9. Где 1 самый быстрый способ сжатия, а 9 самый медленный, но наиболее эффективный. 

Давайте теперь попробуем создать CSV файл на лету. Для этого нам понадобится модуль 'tempfile'.  Давайте посмотрим на код ниже.

import csv
import tarfile
from tempfile import NamedTemporaryFile

with tarfile.open('/tmp/test.tar', mode='w:gz') as tar:
    with NamedTemporaryFile(mode = 'w') as csv2:
        out2 = csv.writer(csv2, quoting=csv.QUOTE_ALL)
        out2.writerow(['Column 1', 'Column 2'])
        csv2.flush()
        tar.add(csv2.name, "test.csv")

Здесь мы как и в первом примере открываем tar файл. Ниже создается экземпляр класса NamedTemporaryFile. Использование именованных временных файлов вместо неименованных обусловлено лишь тем, что, на мой взгляд, так проще передавать аргументы в функцию tar.add(). На следующей строке создается csv writer, который будет писать в наш временный файл.  В этом пример важно, что при создании NamedTemproraryFIle он создается как байтовый. Соответственно, при попытке записать в csv writer (строка out2.writerow(...)) программа упадет со следующей ошибкой: 'a bytes-like object is required, not 'str'. ​​​​​​​Чтобы избежать этой проблемы нужно выставлять параметр при создании временного файла mode = 'w'. Также, если вам кажется, что вы ничего не записываете в csv файл, можно добавить параметр, чтобы файл не удалялся после закрытия, а оставался висеть грузом во временной директории вашей ОС. Для этого воспользуйтесь параметром deleted=false.

Ещё одно важное место где может возникать ошибка - это отсутствие вызова у файла метода flush. В этом случае данные не сбросятся на диск, а следующей командой tar попробует добавить в архив пока что ещё пустой файл. Flush конечно же сработает автоматически, но только после выхода из блока with. А добавление в архив происходит до него.

Также стоит добавить, что если вы хотите добавить в архив два файла, то просто создайте ещё один временный файл, заполните его и выполните операцию tar.add().

Это всё что вам необходимо для создания архива с двумя генерируемыми на лету CSV файлами. Надеюсь, что заметка помогла вам решить вашу проблему. На этом, пожалуй, откланяюсь.