我从S3复制文件到Cloudfiles,我想避免将文件写入磁盘。 Python-Cloudfiles库有一个object.stream()调用,它看起来是我所需要的,但我无法在boto中找到等效的调用。我希望我能像做:如何使用boto将文件从Amazon S3流式传输到Rackspace Cloudfiles?
shutil.copyfileobj(s3Object.stream(),rsObject.stream())
这可能与伯特(或我想任何其他S3库)?
我从S3复制文件到Cloudfiles,我想避免将文件写入磁盘。 Python-Cloudfiles库有一个object.stream()调用,它看起来是我所需要的,但我无法在boto中找到等效的调用。我希望我能像做:如何使用boto将文件从Amazon S3流式传输到Rackspace Cloudfiles?
shutil.copyfileobj(s3Object.stream(),rsObject.stream())
这可能与伯特(或我想任何其他S3库)?
在博托重点对象,它代表在S3对象,可以像使用迭代器,所以你应该能够做这样的事情:
>>> import boto
>>> c = boto.connect_s3()
>>> bucket = c.lookup('garnaat_pub')
>>> key = bucket.lookup('Scan1.jpg')
>>> for bytes in key:
... write bytes to output stream
或者,在你的例子中,你可以这样做:
>>> shutil.copyfileobj(key, rsObject.stream())
这样一个设计良好的图书馆:) – ehacinom
我估计至少一些人看到这个问题会像我,会想办法到流通过线从博托线文件(或逗号逗号,或者任何其他分隔符)。这里有一个简单的方法来做到这一点:
def getS3ResultsAsIterator(self, aws_access_info, key, prefix):
s3_conn = S3Connection(**aws_access)
bucket_obj = s3_conn.get_bucket(key)
# go through the list of files in the key
for f in bucket_obj.list(prefix=prefix):
unfinished_line = ''
for byte in f:
byte = unfinished_line + byte
#split on whatever, or use a regex with re.split()
lines = byte.split('\n')
unfinished_line = lines.pop()
for line in lines:
yield line
@ garnaat上面的答案仍然很好,100%为真。希望我仍然可以帮助别人。
此线程中的其他答案都与boto相关,但S3.Object在boto3中不再可迭代。因此,下面不工作,它产生一个TypeError: 's3.Object' object is not iterable
错误消息:
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)
在boto3,该对象的内容提供的S3.Object.get()['Body']
这不是一个可迭代或者,所以下面仍然不起作用:
body = s3_obj.get()['Body']
with io.FileIO('sample.txt', 'w') as file:
for i in body:
file.write(i)
因此,另一种是使用读法,但这种加载整个S3对象,其中的大文件打交道时内存并不总是一种可能性:
body = s3_obj.get()['Body']
with io.FileIO('sample.txt', 'w') as file:
for i in body.read():
file.write(i)
但read
方法允许传入amt
参数,该参数指定我们要从基础流读取的字节数。此方法可以反复调用,直到整个流已读:
body = s3_obj.get()['Body']
with io.FileIO('sample.txt', 'w') as file:
while file.write(body.read(amt=512)):
pass
挖掘到botocore.response.StreamingBody
代码人们认识到底层流也可用,所以我们可以遍历如下:
body = s3_obj.get()['Body']
with io.FileIO('sample.txt', 'w') as file:
for b in body._raw_stream:
file.write(b)
虽然谷歌上搜索我也看到了一些链接,可以使用的,但我没试过:
非常有用的答案。谢谢@smallo。我很欣赏你揭示了我认为大多数人都在寻找的private __raw_stream。 – saccharine
这是我的包裹的溶液流体:
import io
class S3ObjectInterator(io.RawIOBase):
def __init__(self, bucket, key):
"""Initialize with S3 bucket and key names"""
self.s3c = boto3.client('s3')
self.obj_stream = self.s3c.get_object(Bucket=bucket, Key=key)['Body']
def read(self, n=-1):
"""Read from the stream"""
return self.obj_stream.read() if n == -1 else self.obj_stream.read(n)
实例:
obj_stream = S3ObjectInterator(bucket, key)
for line in obj_stream:
print line
的〔smart_open](https://github.com/piskvorky/smart_open)Python库这样做(阅读和写作)。 – Radim