Glueジョブの引数にJSONを渡す方法

2021.05.28

データアナリティクス事業本部の森脇です。

Sparkを簡単に動かしたい場合にAWS Glueジョブは非常に便利です。

AWS Glueジョブは実行時に引数を渡すことができますが、JSONのような構造化データをそのまま渡すことができるのか、気になったので調べてみました。

AWSの公式ドキュメントから調べてみる

https://docs.aws.amazon.com/ja_jp/glue/latest/dg/aws-glue-programming-python-calling.htmlに記載がありました。

ネストされた JSON 文字列である引数を渡す場合、AWS Glue ETL ジョブに渡されるときにパラメータ値を保持するには、ジョブの実行を開始する前にパラメータ文字列をエンコードし、パラメータ文字列をデコードしてからジョブ・スクリプトを参照する必要があります。

JSONを渡したい場合、エンコードする必要があるようです。

上記ドキュメントにサンプルがのっていたので、それを試してみます。

JSON文字列をそのまま渡すケース

ネストした辞書をJSON文字列に変換し、そのままジョブの引数に渡してみます。

import json
import boto3

glue = boto3.client('glue')

sample = {"a": {"b": {"c": [{"d": {"e": 42}}]}}}

sample_json = json.dumps(sample)

resp = glue.start_job_run(
    JobName="SampleJob",
    Arguments={
        "--SAMPLE": sample_json,
    },
)

print(resp)

ここで実行するとエラーがでるはず。。。なんですが、上手くいってしまいました。

$ python3 run-job-blog.py
{'JobRunId': 'jr_f3351f583e2e3b986061da425b25f7dc8549dfa9bc3c95262da029dfd8028d92', 'ResponseMetadata': {'RequestId': '5c2a96c7-74a3-458f-854f-1639e8c9a955', 'HTTPStatusCode': 200, 'HTTPHeaders': {'date': 'Fri, 28 May 2021 02:13:01 GMT', 'content-type': 'application/x-amz-json-1.1', 'content-length': '82', 'connection': 'keep-alive', 'x-amzn-requestid': '5c2a96c7-74a3-458f-854f-1639e8c9a955'}, 'RetryAttempts': 0}}

Glueジョブ側のログでも、正常に認識されていました。

エラーになってほしかったんですが、場合によってはエンコードしなくても引数に指定できるようです。

base64にエンコードして渡すケース

推奨の方法である、base64エンコードして渡します。

import json
import boto3
import base64


glue = boto3.client('glue')

sample = {"a": {"b": {"c": [{"d": {"e": 42}}]}}}

sample_json = json.dumps(sample)
encoded = base64.b64encode(sample_json.encode("ascii"))
encoded_str = encoded.decode("ascii")


resp = glue.start_job_run(
    JobName="ProtoCreateHudiTable",
    Arguments={
        "--SAMPLE": encoded_str,
    },
)

print(resp)

Glueジョブ側のコードでデコードする必要がありますが、こちらの方が安全に渡せますね。

まとめ

GlueジョブでJSONを渡す方法を調べてみました。

JSON文字列を直接指定して問題ないケースはあるのものの、base64等でデコードするのが良さそうでした。

参考