我在从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“和"file2.txt”的whatevs.tar.gz文件。
如果我将'w:gz‘替换为'w’(并去掉.gz结尾),我会得到一个包含正确内容的tar.gz文件,但将其添加回来会导致一个10字节的损坏tarfile文件
我想把它写成一个字节,因为我实际上是在把它上传到S3。
我不确定我是不是严重误读了这里的文档,我看了上百万篇文章,它们要么生成tar文件(它工作得很好,但我不想要),要么写入本地文件系统(同样,我正在上传到S3,我不想在本地写入)。
谢谢!
发布于 2019-02-18 19:12:09
我认为关闭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)
https://stackoverflow.com/questions/53306000
复制相似问题