背景
BigQueryのクエリ結果をGCSに吐き出したものを社内に展開してエクセルで閲覧してほしい状況。
BigQuery -> GCS はutf8で結果を吐き出すので、エクセルで開くと日本語が文字化けしてしまう。
そこで、バケットにファイルを入れたら勝手にbom付きutf8に変換される cloud functionsを実装する。
Cloud Function with Python
初めて触る場合はこのあたりを読んで触っておくと良さげ
Cloud Storageで発火する関数
Cloud Storageにオブジェクトが作成されたら発火する関数とかが作れる
Cloud Storageのチュートリアル#オブジェクトのファイナライズ
サンプル
bucketに上がったファイルをbom付きutf8に変換し、prefixに bom_
をつけてuploadする関数
from google.cloud import storage
def convert_to_bom(data, context):
bucket_name = data['bucket']
file_path = data['name']
prefix = 'bom_'
file_path_arr = file_path.split('/')
file_name = file_path_arr[-1]
if file_name.startswith(prefix):
return 'skipping of bom file.'
dir_arr = file_path_arr[:-1]
dir_path = '/'.join(dir_arr) + '/'
local_file_path = '/tmp/' + file_name
if(len(file_path_arr) == 1):
new_file_path = prefix + file_path
else:
new_file_path = dir_path + prefix + file_name
client = storage.Client()
bucket = client.get_bucket(bucket_name)
dl_blob = bucket.get_blob(file_path)
up_blob = bucket.blob(new_file_path)
with open(local_file_path, 'w', newline='', encoding='utf_8_sig', errors='ignore') as f:
f.write(dl_blob.download_as_string().decode('utf8'))
up_blob.upload_from_filename(local_file_path)
return 'success'
-i https://pypi.org/simple
cachetools==4.1.0
certifi==2020.4.5.1
chardet==3.0.4
google-api-core==1.19.0
google-auth==1.16.1
google-cloud-core==1.3.0
google-cloud-storage==1.28.1
google-resumable-media==0.5.1
googleapis-common-protos==1.52.0
idna==2.9
protobuf==3.12.2
pyasn1-modules==0.2.8
pyasn1==0.4.8
pytz==2020.1
requests==2.23.0
rsa==4.0
six==1.15.0
urllib3==1.25.9
デプロイ
gcloud functions deploy convert_to_bom --runtime python37 --trigger-resource ${YOUR_BUCKET} --trigger-event google.storage.object.finalize
ファイル書き込み時の注意点
/tmp
以外のディレクトリには書き込みできないので気をつける。書き込もうとすると関数がcrashして静かに死ぬ。
ファイル システムで書き込み可能な部分は /tmp ディレクトリだけです。このディレクトリは、関数インスタンスの一時ファイルの保存先として使用できます。
参考
[Python Client for Google Cloud Storage](Python Client for Google Cloud Storage)
[GoogleCloudStorage] GCSのPythonAPIの使い方 [備忘]