首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >S3.Client.upload_file()和S3.Client.upload_fileobj()有什么区别?

S3.Client.upload_file()和S3.Client.upload_fileobj()有什么区别?
EN

Stack Overflow用户
提问于 2018-09-15 01:43:07
回答 4查看 19.3K关注 0票数 14

根据S3.Client.upload_fileS3.Client.upload_fileobj的说法,upload_fileobj听起来可能更快。但有没有人知道具体细节?我应该只上传文件,还是应该以二进制模式打开文件以使用upload_fileobj?换句话说,

代码语言:javascript
运行
复制
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哪个更好?有什么不同吗?

EN

回答 4

Stack Overflow用户

发布于 2018-09-15 02:24:19

upload_fileobj的要点是,文件对象不必首先存储在本地磁盘上,而是可以在内存中表示为文件对象。

Python为此目的提供了standard library module

代码将如下所示

代码语言:javascript
运行
复制
import io
fo = io.BytesIO(b'my data stored as file object in RAM')
s3.upload_fileobj(fo, 'mybucket', 'hello.txt')

在这种情况下,它的执行速度会更快,因为您不必从本地磁盘读取数据。

票数 16
EN

Stack Overflow用户

发布于 2018-09-15 02:09:41

TL;DR

就速度而言,这两种方法的执行大致相同,都是用python编写的,瓶颈要么是disk-io (从磁盘读取文件),要么是network-io (写入s3)。

  • 在编写仅处理从磁盘上载文件的代码时使用upload_file()
  • 在您编写处理s3上载的通用代码时使用upload_fileobj(),这些上载将来不仅可用于磁盘上的文件。

fileobj到底是什么?

在包括python标准库在内的多个地方都有这样的约定,即当使用术语fileobj时,她的意思是file-like object。甚至还有一些库公开函数,这些函数可以将文件路径(str)或文件对象( fileobj )作为相同的参数。

当使用文件对象时,您的代码并不仅限于磁盘,例如:

例如,

  1. 您可以以流的方式将数据从一个s3对象复制到另一个对象(不会占用磁盘空间,也不会减慢对磁盘执行io读/写操作的过程)。
  2. 您可以在将对象写入S3

时动态压缩或解密数据

以通用方式使用python gzip模块和类文件对象的示例:

代码语言:javascript
运行
复制
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:

代码语言:javascript
运行
复制
tarfile.open(name=None, mode='r', fileobj=None, bufsize=10240, **kwargs)

使用s3.upload_fileobj()进行动态压缩的示例

代码语言:javascript
运行
复制
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)
票数 8
EN

Stack Overflow用户

发布于 2018-09-15 02:05:42

两者都不是更好,因为它们是不可比较的。虽然最终结果是相同的(一个对象被上传到S3),但它们的来源完全不同。一种是希望您提供要上传的文件在磁盘上的路径,而另一种是希望您提供一个类似文件的对象。

如果您在磁盘上有一个文件,并且想要上传它,那么使用upload_file。如果你有一个类似文件的对象(最终可能是很多东西,包括一个打开的文件,一个流,一个套接字,一个缓冲区,一个字符串),那么使用upload_fileobj

在此上下文中的“类文件对象”是任何实现read方法并返回字节的对象。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52336902

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档