Python(boto3)でAWS S3に進捗表示させながらファイルアップロードする
AWS SDK for Python(boto3)を使用してS3にファイルをアップロードする方法は調べたらすぐ出てくるものの、進捗表示と組み合わせるとなるとなかなか情報が少なかったので(調べ方が下手なだけかもしれないけど)、試行錯誤した結果を記録しておこうと思います。
今回はupload_fileを使います。
早速コード
様々な処理の合間に書いてたコードを抜粋しただけなので、これだけの動作確認はしてません。
import threading import os import boto3 class FileUploadTestClass: def __init__(self): super().__init__() self._filepath = '/%PATH%/test.txt' self._filesize = float(os.path.getsize(self._filepath)) self._transfer_size = 0 self._lock = threading.Lock() def file_upload_test(self): s3_bucket_name = 's3_bucket_name' # S3のバケット名 s3_uploadfile_path = 'test/test.txt' # アップロード先のパス s3 = boto3.resource('s3') s3_bucket = s3.Bucket(s3_bucket_name) s3_config = boto3.s3.transfer.TransferConfig( use_threads=True, max_concurrency=10, ) try: # ファイルアップロード s3_bucket.upload_file( Filename=self._filepath, Key=s3_trainingdata_path, Callback=self, Config=s3_config, ) except boto3.exceptions.S3UploadFailedError: # ここでエラー時の処理 pass def __call__(self, bytes_amount): with self._lock: self._transfer_size += bytes_amount percentage = (self._transfer_size / self._filesize) * 100 # 進捗をコンソール出力 print('{0} {1} / {2} ({3}%)'.format(self._filename, self._transfer_size, self._filesize, percentage)) # ここでログファイルに書き込んだりetc
upload_fileのCallbackには、クラスを指定します。
今回はselfにしたけど、別のクラスを作成して指定しても良いです。
ここで指定したクラスの、__call__関数が呼ばれます。__call__はクラス名を指定すると呼ばれる関数、だったかな…。
引数にbytes_amount
これはその時転送したバイト数なので、どんどん足していくことで今までに何バイト転送できたかが分かります。
ちなみにupload_fileのCofigには事前にboto3.s3.transfer.TransferConfigで作成した設定を入れます。
今回のコードでは
use_threads=True,
max_concurrency=10,
として、10スレッドで平行に処理させてアップロード速度アップさせてます。
このスレッドにはmainスレッドも含まれるので注意。アップロード中に他のことやりたかったら、ファイルアップロード処理自体をスレッドクラスのrunの中でやるとかしなきゃいけないです。
以上。
参考: 公式ドキュメント
https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/s3.html#S3.Client.upload_file
https://boto3.amazonaws.com/v1/documentation/api/latest/guide/s3-uploading-files.html