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の方が優れていますか?違いはありますか?
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')
その場合、ローカルディスクから読み取る必要がないため、パフォーマンスが向上します。
速度に関しては、どちらの方法もほぼ同じように実行され、両方ともpythonで記述され、ボトルネックはdisk-io(ディスクからファイルを読み取る)またはnetwork-io(s3に書き込む)のいずれかになります) 。
upload_file()
を使用します。upload_fileobj()
を使用します。python標準ライブラリを含む複数の場所での慣習があります。fileobj
という用語を使用している場合、彼女は ファイルのようなオブジェクト を意味します。同じパラメーターとしてファイルパス(str)またはfileobj(ファイルのようなオブジェクト)を取ることができる関数を公開する一部のライブラリーです。
ファイルオブジェクトを使用する場合、コードはディスクのみに限定されません。たとえば、次のようになります。
たとえば、1つの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 一方、2つのパラメーター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)
_
それらは比較できないので、どちらも良くありません。最終結果は同じですが(オブジェクトがS3にアップロードされます)、そのオブジェクトのソースはまったく異なります。 1つはアップロードするファイルのディスク上のパスを指定することを期待し、もう1つはファイルのようなオブジェクトを提供することを期待しています。
ディスクにファイルがあり、それをアップロードする場合は、upload_file
を使用します。ファイルのようなオブジェクト(最終的には、開いているファイル、ストリーム、ソケット、バッファ、文字列など、多くのことになる)がある場合は、upload_fileobj
を使用します。
このコンテキストでの「ファイルのようなオブジェクト」は、read
メソッドを実装し、バイトを返すものです。
https://boto3.amazonaws.com/v1/documentation/api/1.9.185/guide/s3-uploading-files.html のドキュメントに従って
"upload_fileメソッドとupload_fileobjメソッドは、S3クライアント、バケット、オブジェクトの各クラスによって提供されます。各クラスが提供するメソッドの機能は同じです。あるクラスのメソッドを別のクラスのメソッドを呼び出すことによる利点はありません。最も便利なクラスを使用してください。」
上記の答えは間違っているようです