如何使用boto将文件从Amazon S3流式传输到Rackspace Cloudfiles?

2024-04-26 09:46:55 发布

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

我正在将一个文件从S3复制到Cloudfiles,我希望避免将该文件写入磁盘。Python Cloudfiles库有一个object.stream()调用,看起来是我需要的,但是在boto中找不到等效的调用。我希望我能做些类似的事情:

shutil.copyfileobj(s3Object.stream(),rsObject.stream())

这在boto(或者我想还有其他的s3库)中是可能的吗?


Tags: 文件streamobjects3事情cloudfiles磁盘boto
3条回答

boto中的键对象表示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())

我想至少有一些人看到这个问题会像我一样,希望有一种方法从boto逐行(或逗号,逗号,或任何其他分隔符)流文件。有一个简单的方法:

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']处可用,这是一个不可接受的版本,因为1.9.68以前没有。因此,以下内容适用于最新版本的boto3,但不适用于较早版本的boto3:

body = s3_obj.get()['Body']
with io.FileIO('sample.txt', 'w') as file:
    for i in body:
        file.write(i)

因此,旧版本boto3的另一种选择是使用read方法,但这会将整个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)

在谷歌搜索时,我也看到了一些可以使用的链接,但我没有尝试:

相关问题 更多 >