Fla*_*air 5 python amazon-s3 amazon-web-services python-3.x boto3
根据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')
Run Code Online (Sandbox Code Playgroud)
版本1或版本2更好吗?有区别吗?
在速度方面,两种方法的性能大致相同,都是用python编写的,瓶颈是disk-io(从磁盘读取文件)或network-io(写入s3)。
upload_file()在编写仅处理从磁盘上传文件的代码时使用。upload_fileobj()当您编写通用代码来处理 s3 上传时使用,这些代码将来不仅可以用于磁盘用例中的文件。在包括 python 标准库在内的多个地方都有约定,当人们使用术语fileobjshe 时表示类似文件的对象。甚至有些库公开了可以将文件路径 (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())
Run Code Online (Sandbox Code Playgroud)
另一方面,tarfile有两个参数 file & fileobj:
tarfile.open(name=None, mode='r', fileobj=None, bufsize=10240, **kwargs)
Run Code Online (Sandbox Code Playgroud)
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)
Run Code Online (Sandbox Code Playgroud)
要点upload_fileobj是,文件对象不必首先存储在本地磁盘上,而可以表示为RAM中的文件对象。
Python 为此具有标准的库模块。
代码看起来像
import io
fo = io.BytesIO(b'my data stored as file object in RAM')
s3.upload_fileobj(fo, 'mybucket', 'hello.txt')
Run Code Online (Sandbox Code Playgroud)
在这种情况下,由于您不必从本地磁盘读取数据,因此它将更快地执行。
两者都没有更好,因为它们没有可比性。虽然最终结果是相同的(一个对象上传到 S3),但它们获取该对象的方式却截然不同。一个期望您提供要上传的文件在磁盘上的路径,而另一个期望您提供一个类似文件的对象。
如果磁盘上有文件并想要上传它,请使用upload_file. 如果您有一个类似文件的对象(最终可能是很多东西,包括打开的文件、流、套接字、缓冲区、字符串),那么使用upload_fileobj.
在这种情况下,“类文件对象”是实现该read方法并返回字节的任何对象。
| 归档时间: |
|
| 查看次数: |
4184 次 |
| 最近记录: |