根据S3.Client.upload_file和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哪个更好?有什么不同吗?
发布于 2018-09-15 02:24:19
upload_fileobj
的要点是,文件对象不必首先存储在本地磁盘上,而是可以在内存中表示为文件对象。
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')
在这种情况下,它的执行速度会更快,因为您不必从本地磁盘读取数据。
发布于 2018-09-15 02:09:41
TL;DR
就速度而言,这两种方法的执行大致相同,都是用python编写的,瓶颈要么是disk-io (从磁盘读取文件),要么是network-io (写入s3)。
upload_file()
。upload_fileobj()
,这些上载将来不仅可用于磁盘上的文件。fileobj到底是什么?
在包括python标准库在内的多个地方都有这样的约定,即当使用术语fileobj
时,她的意思是file-like object。甚至还有一些库公开函数,这些函数可以将文件路径(str)或文件对象( fileobj )作为相同的参数。
当使用文件对象时,您的代码并不仅限于磁盘,例如:
例如,
时动态压缩或解密数据
以通用方式使用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)
发布于 2018-09-15 02:05:42
两者都不是更好,因为它们是不可比较的。虽然最终结果是相同的(一个对象被上传到S3),但它们的来源完全不同。一种是希望您提供要上传的文件在磁盘上的路径,而另一种是希望您提供一个类似文件的对象。
如果您在磁盘上有一个文件,并且想要上传它,那么使用upload_file
。如果你有一个类似文件的对象(最终可能是很多东西,包括一个打开的文件,一个流,一个套接字,一个缓冲区,一个字符串),那么使用upload_fileobj
。
在此上下文中的“类文件对象”是任何实现read
方法并返回字节的对象。
https://stackoverflow.com/questions/52336902
复制相似问题