GlueのPython Shellジョブでファイルの文字コードを変更してみた
こんにちは。DI部の大高です。
突然ですが「AWS Glueと仲良くなりたい!」ということで、初心者ながら色々とGlueを触ってみたいと思います。これからGlueを触る方向けに参考になれば幸いです。
Glueのジョブは「Spark」ジョブと「Python Shell」ジョブの2タイプがありますが、今回はよりシンプルなジョブだと思われる「Python Shell」ジョブを使ってS3のファイルを処理してみました。
やりたいこと
以下のような流れを想定して、主にファイルの文字コード処理にフォーカスしてジョブを作ってみたいと思います。
- ユーザがExcelで作成したファイルをタブ区切りのファイルとして保存する(この時点での文字コードは"Shift_JIS")
- ユーザは保存したファイルをS3にアップロードする
- S3にアップロードされたファイルをGlueのジョブで読み込んで、文字コードを"UTF-8"にしてS3に保存する
データの準備
まずはデータを準備します。データは以下のようなExcelファイルを作成し、保存時に「テキスト (タブ区切り) (*.txt)」として保存します。また、今回はファイル名をSample.in.tsv
として保存しました。
No Title Price 1 劇場版 仮面ライダービルド Be The One 6192.1 2 平成仮面ライダー20作記念 仮面ライダー平成ジェネレーションズ FOREVER 7115.2 3 ビルド NEW WORLD 仮面ライダークローズ 9720.3
このファイルをS3にアップロードします。適当に作成したバケット内のフォルダに配置しておきます。
IAMロールの準備
データの準備ができたので、早速Python Shellジョブを作成したいところですが、その前に権限回りも準備しておきます。
以下の記事を参考にGlue用のIAMロールを準備しました。なお、今回は開発用エンドポイントは利用しないので、参考記事内のStep4と5は飛ばしています。
GlueのPython Shellジョブの作成
さて、準備が出来たのでPython Shellジョブを作成します。マネージメントコンソールからGlueの画面を開き「ジョブの追加」をクリックします。
ジョブには適宜名前を付けて、先程準備したIAMロールを指定します。また「Type」にはPython shell
を指定し、「このジョブ実行」としてはユーザーが作成する新しいスクリプト
を指定します。スクリプト保存先はデフォルトのままでも良いですが、ちょっと個人用にパスを変えています。
その他はデフォルトのままで「次へ」ボタンをクリックします。次の画面では接続情報の設定ができますが、今回は何も設定せずに保存してスクリプト編集画面へ移ります。
スクリプトの編集
さて、記述するPythonスクリプトですが以下のようなスクリプトになります。
import boto3 import sys from awsglue.utils import getResolvedOptions #SRC_BUCKET_NAME='sample-bucket' #SRC_OBJECT_KEY_NAME='glue/Sample.in.tsv' #SRC_FILE_ENCODING='shift_jis' #DEST_BUCKET_NAME='sample-bucket' #DEST_OBJECT_KEY_NAME='glue/Sample.out.tsv' # ジョブパラメータの読み込み args = getResolvedOptions(sys.argv, ['SRC_BUCKET_NAME', 'SRC_OBJECT_KEY_NAME', 'SRC_FILE_ENCODING', 'DEST_BUCKET_NAME', 'DEST_OBJECT_KEY_NAME']) print('args: {0}'.format(args)) # S3 Service Resource 準備 s3 = boto3.resource('s3') # ファイルをロード src_obj = s3.Object(args['SRC_BUCKET_NAME'], args['SRC_OBJECT_KEY_NAME']) body = src_obj.get()['Body'].read().decode(args['SRC_FILE_ENCODING']) # ファイルを保存 dest_obj = s3.Object(args['DEST_BUCKET_NAME'], args['DEST_OBJECT_KEY_NAME']) dest_obj.put(Body = body)
ジョブパラメータ
コメントアウトしている箇所は、ジョブパラメータの値の参考値です。ジョブ作成時にデフォルトのままにして飛ばしたのですが、Glueのジョブは「ジョブパラメータ」として「キー」と「値」でパラメータを指定できます。これは後でジョブの設定を変更して設定します。
指定したパラメータはgetResolvedOptions
を利用して読み込みます。ここの第二引数でちゃんと指定しないとargs
には格納されないので注意します。また、確認のために値をprint
で出力させて見ました。
getResolvedOptions を使用して、パラメータにアクセスする - AWS Glue
ファイルの取得と保存
S3へのアクセスはboto3
を利用しています。
S3から読み込み先パスにあるファイルをs3.Object
を利用してsrc_obj
として定義し、get()['Body'].read()
で読み込んでいます。また、文字コードがShift_JIS
のファイルなのでdecode
で文字コードを指定して読み込みます。
これでUTF-8
のデータになったので、同様にして保存先をdest_obj
として定義して、put(Body = body)
で保存しています。
スクリプトは以上のように単純なものになります。
ジョブパラメータを設定する
最後に、先程スクリプト内で利用したジョブパラメータを設定します。ジョブ一覧に戻り、ジョブにチェックを入れて「アクション」から「ジョブの編集」をクリックします。
ジョブの編集画面では真ん中ぐらいまでスクロールすると「セキュリティ設定、スクリプトライブラリおよびジョブパラメータ (省略可能)」という箇所があるので、開きます。
すると、更に下の方に「ジョブパラメータ」の設定箇所があるので、ここに「キー」と「値」を設定していきます。ここで一番注意が必要なのは キーの先頭に--
が必要 ということです。始めはこれに気が付かなくて、ちょっとハマりました。
Pythonスクリプト内では、キーの先頭に--
は不要ですが、ここの「キー」では必要なので注意して下さい。
いざ、実行!
これで準備万端です。ジョブを実行してみます。先程と同様にジョブ一覧からジョブにチェックを入れて「アクション」から「ジョブの実行」をクリックします。
すると、ジョブ実行ウィンドウが開くので「ジョブの実行」をクリックします。するとジョブ一覧の上部にジョブ実行中の旨が表示されます。
表示が消えたら再度ジョブを選択すると、以下のように表示されて「Succeeded」ステータスになっていることが確認できます。「ログ」もクリックして確認してみましょう。
スクリプトに記述した通り、ジョブパラメータが出力されていますね。
肝心のS3に保存したファイルも確認してみましょう。以下のとおり出力されています。
ファイルをダウンロードして確認したところ、文字コードもちゃんとUTF-8
になっていました!
まとめ
まずはPython Shellジョブを触ってみました。こちらは単純に普段書くようなPythonコードとさほど変わらないので書きやすいですね。今後はここから少しずつ発展して、もっとGlueと仲良くなっていきたいと思います。
どなたかのお役に立てれば幸いです。それでは!