根据https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/s3.html#S3.Client.upload_file和https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/s3.html#S3.Client.upload_fileobj,upload_fileobj
听起来可能更快。但是有人知道细节吗?我应该上传文件还是以二进制模式打开文件以使用upload_fileobj
?换句话说,
import boto3
s3 = boto3.resource('s3')
### Version 1
s3.meta.client.upload_file('/tmp/hello.txt', 'mybucket', 'hello.txt')
### Version 2
with open('/tmp/hello.txt', 'rb') as data:
s3.upload_fileobj(data, 'mybucket', 'hello.txt')
第1版或第2版更好吗?有区别吗?
答案 0 :(得分:4)
就速度而言,这两种方法的性能大致相同,都是用python编写的,而瓶颈将是disk-io(从磁盘读取文件)或network-io(写入s3)。
upload_file()
。upload_fileobj()
,将来可能不仅对磁盘用例中的文件重复使用s3上传。
在很多地方都有约定,包括python标准库,当人们使用术语fileobj
时,她的意思是file-like object。
甚至有一些库公开了可以将文件路径(str)或fileobj(类似文件的对象)作为相同参数的函数。
使用文件对象时,您的代码不仅限于磁盘,例如:
例如,您可以以流方式将数据从一个s3对象复制到另一个对象中(无需使用磁盘空间或减慢对磁盘执行读/写io的过程)。
在将对象写入S3时,您可以即时(解)压缩或解密数据
将python gzip模块与类文件对象以通用方式一起使用的示例:
import gzip, io
def gzip_greet_file(fileobj):
"""write gzipped hello message to a file"""
with gzip.open(filename=fileobj, mode='wb') as fp:
fp.write(b'hello!')
# using opened file
gzip_greet_file(open('/tmp/a.gz', 'wb'))
# using filename from disk
gzip_greet_file('/tmp/b.gz')
# using io buffer
file = io.BytesIO()
gzip_greet_file(file)
file.seek(0)
print(file.getvalue())
另一方面,tarfile具有两个参数file和fileobj:
tarfile.open(name=None, mode='r', fileobj=None, bufsize=10240, **kwargs)
s3.upload_fileobj()
即时压缩的示例import gzip, boto3
s3 = boto3.resource('s3')
def upload_file(fileobj, bucket, key, compress=False):
if compress:
fileobj = gzip.GzipFile(fileobj=fileobj, mode='rb')
key = key + '.gz'
s3.upload_fileobj(fileobj, bucket, key)
答案 1 :(得分:4)
upload_fileobj
的要点是,文件对象不必首先存储在本地磁盘上,而可以表示为RAM中的文件对象。
Python为此目的有standard library module。
代码看起来像
import io
fo = io.BytesIO(b'my data stored as file object in RAM')
s3.upload_fileobj(fo, 'mybucket', 'hello.txt')
在这种情况下,由于您不必从本地磁盘读取数据,因此它的执行速度更快。
答案 2 :(得分:1)
根据https://boto3.amazonaws.com/v1/documentation/api/1.9.185/guide/s3-uploading-files.html
中的文档” upload_file和upload_fileobj方法由S3 Client,Bucket和Object类提供。每个类提供的方法功能是相同的。通过调用一个类的方法来获得另一个类没有任何益处。使用任何一个类最方便。”
以上答案似乎是错误的