问题描述
我在 s3 中有一个很大的 tar 文件(10s 的 GB)。它包含许多 tar.gz 文件。
s3_client = boto3.client('s3')
input = s3_client.get_object(Bucket=bucket,Key=key)
with tarfile.open(fileobj=input['Body'],mode='r|') as tar:
print(tar) -- tarinfo
我希望能够以流式方式执行此操作,而不是将整个文件加载到内存中。
我试过做类似的事情
tar.extract_file(tar.next)
但我不确定像对象这样的文件是如何可读的。
--- 编辑
在@larsks 的帮助下,我取得了一些进展。
with tarfile.open(fileobj=input_tar_file['Body'],mode='r|') as tar:
for item in tar:
m = tar.extractfile(item)
if m is not None:
with tarfile.open(fileobj=m,mode='r|gz') as gz:
for data in gz:
d = gz.extractfile(data)
但是,如果我在 d 上调用 .read()。它是空的。如果我遍历 d.raw.fileobj.read() 有数据。但是当我写出来时,它是来自嵌套 tar.gz 中所有文本文件的数据,而不是一个一个。
解决方法
tar.extractfile
的返回值是一个“类文件对象”,就像 input['Body']
一样。这意味着您可以简单地将其传递给 tarfile.open
。这是一个打印嵌套存档内容的简单示例:
import tarfile
with open('outside.tar','rb') as fd:
with tarfile.open(fileobj=fd,mode='r') as outside:
for item in outside:
with outside.extractfile(item) as inside:
with tarfile.open(fileobj=inside,mode='r') as inside_tar:
for item in inside_tar:
data = inside_tar.extractfile(item)
print('content:',data.read())
这里的“外部”文件是一个实际的文件,而不是什么东西
来自 S3 存储桶;但我先打开它以便我们仍然
打开外部存档时传入 fileobj
。
代码遍历外部存档 (for item in outside
) 的内容,并针对以下每个项目:
- 使用
outside.extractfile()
打开文件
- 将其作为参数传递给
fileobj
参数tarfile.open
- 提取嵌套 tarfile 中的每个项目