🌊
S3にあるファイルをzipに圧縮してそのままアップロードするPythonスクリプト
はじめに
S3に置いてあるファイルを、まとめてzipにしたいことってありませんか?
今回は、PythonでS3のファイルを扱うのに便利なs3fs
というライブラリを利用して上記のことを実施します。
コード
やっていることはシンプルなのでソースコードのみ載せます。
今回はビルトインライブラリのzipfileを利用しましたが、他のgzipとかでも同様にできるはずです。
import io
import zipfile
import s3fs
fs = s3fs.S3FileSystem(anon=False)
S3_BUCKET_NAME = "{YOUR_BUCKET_NAME}"
S3_ZIP_OUTPUT_FULL_PATH = "s3://.../.../file.zip"
# s3fsだと * で複数のファイルを一度に選択できます。
file_paths = [f"s3://{f}" for f in fs.glob(f"s3://{S3_BUCKET_NAME}/path/to/files=*")]
file_names = [f.split("/")[-1] for f in file_paths]
# zipのstreamを作成して、順次ファイルを読み込んでいく
zip_stream = io.BytesIO()
with zipfile.ZipFile(zip_stream, 'w', compression=zipfile.ZIP_DEFLATED) as new_zip:
for file_name, file_path in zip(file_names, file_paths):
# file_pathにはS3のフルパスが、
# file_nameにはzipに格納する時に入るファイル名です。
# 現在だと、zipの直下に入れるようになっているので、フォルダを分けたい場合は
# 適宜 `/` で区切るようにしてください。
new_zip.writestr(file_name, fs.open(file_path, "rb").read())
# 書き込み処理
zip_stream.seek(0)
with fs.open(S3_ZIP_OUTPUT_FULL_PATH, "wb") as f:
f.write(zip_stream.read())
Pythonのdict
をそのままアップロードしたい場合は次のようなコードになります。
import json
data = {"key1": "value1"}
zip_stream = io.BytesIO()
with zipfile.ZipFile(zip_stream, 'w', compression=zipfile.ZIP_DEFLATED) as new_zip:
json_stream = io.StringIO()
json.dump(data, json_stream)
new_zip.writestr("role_mapping.json", bytes(json_stream.getvalue(), encoding="utf-8"))
おわりに
今回、記事を作成したきっかけがここ半年くらいで
2回ほどS3にあるファイルをzipにまとめて上げるみたいなことをしており、
ネットを探してもパッとは出てこなかったので記事にまとめました。
備忘録的な側面が強いですが誰かの役に立てば嬉しいです。
Discussion