<p>这个线程中的其他答案与boto有关,但是S3.Object在boto3中不再是不可接受的。因此,以下操作不起作用,它将生成一条<code>TypeError: 's3.Object' object is not iterable</code>错误消息:</p>
<pre><code>s3 = boto3.session.Session(profile_name=my_profile).resource('s3')
s3_obj = s3.Object(bucket_name=my_bucket, key=my_key)
with io.FileIO('sample.txt', 'w') as file:
for i in s3_obj:
file.write(i)
</code></pre>
<p>在boto3中,对象的内容在<code>S3.Object.get()['Body']</code>处可用,这是一个不可接受的版本,因为<a href="https://github.com/boto/boto3/blob/3c024441a94b7c6661ce28f7a283d2878115c81a/CHANGELOG.rst#1968" rel="nofollow noreferrer">1.9.68</a>以前没有。因此,以下内容适用于最新版本的boto3,但不适用于较早版本的boto3:</p>
<pre><code>body = s3_obj.get()['Body']
with io.FileIO('sample.txt', 'w') as file:
for i in body:
file.write(i)
</code></pre>
<p>因此,旧版本boto3的另一种选择是使用read方法,但这会将整个S3对象加载到内存中,在处理大型文件时,这并不总是一种可能:</p>
<pre><code>body = s3_obj.get()['Body']
with io.FileIO('sample.txt', 'w') as file:
for i in body.read():
file.write(i)
</code></pre>
<p>但是<code>read</code>方法允许传入指定要从底层流读取的字节数的<code>amt</code>参数。在读取整个流之前,可以重复调用此方法:</p>
<pre><code>body = s3_obj.get()['Body']
with io.FileIO('sample.txt', 'w') as file:
while file.write(body.read(amt=512)):
pass
</code></pre>
<p>深入研究<code>botocore.response.StreamingBody</code>代码,我们会发现底层流也是可用的,因此我们可以按如下方式迭代:</p>
<pre><code>body = s3_obj.get()['Body']
with io.FileIO('sample.txt', 'w') as file:
for b in body._raw_stream:
file.write(b)
</code></pre>
<p>在谷歌搜索时,我也看到了一些可以使用的链接,但我没有尝试:</p>
<ul>
<li><a href="https://www.snip2code.com/Snippet/1102841/Wrap-boto3-s-StreamingBody-object-to-pro" rel="nofollow noreferrer">WrappedStreamingBody</a></li>
<li><a href="https://stackoverflow.com/questions/34570226/how-to-use-botocore-response-streamingbody-as-stdin-pipe">Another related thread</a></li>
<li><a href="https://github.com/boto/boto3/issues/426" rel="nofollow noreferrer">An issue in boto3 github to request StreamingBody is a proper stream</a>-已经关闭!!!</li>
</ul>