我在从BytesIO对象用Python编写.tar.gz文件时遇到问题。只写一个普通的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())
这应该做的是制作一个包含"file1.txt"one_answers"file2.txt"的whatevs.tar.gz文件。
如果我用"w"替换"w:gz"(并删除.gz结尾(,我会得到一个内容正确的tarfile,但将其添加回来会导致一个10字节、损坏的tar.gz文件
我想把它写到字节中,因为我实际上正在把它上传到S3。
我不确定我是否严重误读了这里的文档,我已经浏览了一百万篇帖子,它们要么制作tar文件(效果很好,但我不想(,要么写到本地文件系统(同样,我正在上传到S3,我不想在本地写(。
谢谢!
我认为关闭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)