Добавление BytesIO в BytesIO tar.gz в python - PullRequest
0 голосов
/ 14 ноября 2018

У меня проблемы с записью файла .tar.gz на Python из объекта BytesIO. Написание простого простого tar-файла прекрасно работает, но если я изменю режим записи на .tar.gz (или bz, или xz), он не создаст действительный файл tar.

Я сделал урезанную версию ниже:

def string_to_tarfile(name, string):
    encoded = string.encode('utf-8')
    s = BytesIO(encoded)

    tar_info = tarfile.TarInfo(name=name)
    tar_info.mtime=time.time()
    tar_info.size=len(encoded)

    return s, tar_info

file1='hello'
file2='world'

f=BytesIO()
tar = tarfile.open(fileobj=f, mode='w:gz')
string, tar_info = string_to_tarfile("file1.txt", file1)
tar.addfile(tarinfo=tar_info, fileobj=string)

string, tar_info = string_to_tarfile("file2.txt", file2)
tar.addfile(tarinfo=tar_info, fileobj=string)

f.seek(0)
with open('whatevs.tar.gz', 'wb') as out:
    out.write(f.read())

Что нужно сделать, это сделать файл whatevs.tar.gz с файлами "file1.txt" и "file2.txt".

Если я заменю 'w: gz' на 'w' (и удаляю окончание .gz), я получаю tar-файл с правильным содержимым, но добавление его обратно приводит к 10-байтному поврежденному файлу tar.gz

Я хочу написать это в bytesio, потому что я на самом деле загружаю его на S3.

Я не уверен, неправильно ли я здесь читаю документы, я просмотрел миллион постов, и они либо создают файлы tar (что работает нормально, но я не хочу), либо пишут в локальный файл. система (опять же, я загружаю на S3, я не хочу писать это локально).

Спасибо!

1 Ответ

0 голосов
/ 18 февраля 2019

Я думаю, что закрытие объекта tarfile решит вашу проблему.

f = BytesIO()
tar = tarfile.open(fileobj=f, mode='w:gz')
string, tar_info = string_to_tarfile("file1.txt", file1)
tar.addfile(tarinfo=tar_info, fileobj=string)

string, tar_info = string_to_tarfile("file2.txt", file2)
tar.addfile(tarinfo=tar_info, fileobj=string)
tar.close() # <-- 

Чтобы не испытывать такого рода проблем с открытым файлом, я думаю, что безопаснее использовать его с with оператором, подобным этому:

f = BytesIO()
with tarfile.open(fileobj=f, mode='w:gz') as tar:
    string, tar_info = string_to_tarfile("file1.txt", file1)
    tar.addfile(tarinfo=tar_info, fileobj=string)

    string, tar_info = string_to_tarfile("file2.txt", file2)
    tar.addfile(tarinfo=tar_info, fileobj=string)
...