使用boto3和python从amazons3读取zip文件

2024-09-24 22:20:52 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个s3bucket,它有大量的zip文件,大小以GBs为单位。我需要计算所有zip文件的数据长度。我试过了第三种,但没有收到。 我不确定它是否可以直接读取zip文件,但我有一个过程-

  1. 与铲斗连接。在
  2. 从bucket文件夹中读取zip文件(假设文件夹是Mydata)。在
  3. 将zip文件解压缩到另一个名为Extracteddata的文件夹中。在
  4. 读取Extracteddata文件夹并对文件执行操作。在

注意:不应该在本地存储上下载任何内容。所有过程都在S3到S3之间。 如有任何建议,我们将不胜感激。在


Tags: 文件数据文件夹内容s3bucket过程单位
2条回答

这是不可能的。在

你可以上传文件到amazons3,也可以下载文件。您可以查询对象列表并获取有关对象的元数据。但是,amazons3不提供计算功能,比如zip压缩/解压。在

您需要编写一个程序

  • 下载zip文件
  • 提取文件
  • 对文件执行操作

这可能最好在AmazonEC2实例上进行,该实例对AmazonS3的访问具有低延迟。您可以使用AWS Lambda函数来实现,但它的磁盘存储空间限制为500MB,执行时间为5分钟,这似乎不适合您的情况。在

如果你特别聪明,你可以下载每个zip文件的一部分(“rangeget”),并解释zipfile头以获得文件及其大小的列表,从而避免下载整个文件。在

你想做的事情是不可能的,正如John Rotenstein's answer所解释的那样。您不必将zipfile下载到本地存储,但至少要下载到本地内存,耗尽您的本地带宽。无法在S3上运行任何代码。在

不过,不管怎样,还是有办法得到你真正想要的东西。在

如果你可以下载,比方说,8KB的文件,而不是整个5GB,这就足够了吗?如果是这样,如果你愿意做一点工作,那么你就幸运了。如果你不得不下载,比如说,1MB,但是可以做的工作少很多呢?在


如果1MB听起来不算太糟,而且你愿意接受一些黑客攻击:

您只需要统计zipfile中有多少个文件。对于zipfile,所有这些信息都可以在中心目录中找到,这是文件末尾的一小块数据。在

如果您拥有整个中心目录,即使丢失了文件的其余部分,stdlib中的zipfile模块也能很好地处理它。虽然没有记录到这样做,但是,至少在最近的CPython和pypy3.x中包含的版本中,它肯定会这样做。在

所以,你能做的是:

  • 发出一个^{}请求,只获取标题。(在boto中,使用^{}进行此操作。)
  • Content-Length头提取文件大小。
  • 用一个GET请求一个^{}头,只从size-1048576下载到最后。(在boto中,我相信您可能需要调用^{},而不是download*便利方法之一,并且您必须自己格式化Range头值。)

现在,假设您在缓冲区buf中有最后的1MB:

z = zipfile.ZipFile(io.BytesIO(buf))
count = len(z.filelist)

通常,1MB就足够了。但如果不是呢?好吧,这就是事情变得有些棘手的地方。zipfile模块知道您还需要多少字节,但它提供给您这些信息的唯一位置是异常描述的文本。所以:

^{pr2}$

如果1MB听起来已经太多带宽了,或者您不想依赖zipfile模块的未记录行为,那么您只需要做更多的工作。在

在几乎每种情况下,您甚至不需要整个中心目录,只需要total number of entries字段,end of central directory record字段是位于中心目录末尾的更小的数据块。在

因此,请执行上述操作,但只读取最后8KB而不是最后1MB。在

然后,基于zip format spec,编写自己的解析器。在

当然,您不需要编写完整的解析器,甚至不需要接近它。您只需要处理从total number of entries到最后的字段。除zip64 extensible data sector和/或.ZIP file comment之外,所有这些字段都是固定大小的字段。在

偶尔(例如,对于有大量注释的zipfiles),您需要阅读更多的数据来获得计数。这应该是相当罕见的,但如果出于某种原因,它在你的zipfiles中更常见,你可以把8192的猜测改成更大的值。在

相关问题 更多 >