そうだ、教祖になろう。出エジプト記 第3章2節 LambdaからGoogleスプレッドシートにアクセスする
門の神「ズール」
前回の第3章1節 Cloud9でLambdaの開発環境を構築するではCloud9で開発環境をセットアップしました。 これでサーバサイドを実装できるようになったわけですが、いきなり全部作ると長いので少しずついきましょう。
まずはこのアプリケーションの外部記憶であるところのGoogleスプレッドシートへのアクセスを試してみます。 こういう構成です。
GoogleスプレッドシートへのアクセスはPythonのgspreadというパッケージがやってくれます。
まずは、Googleスプレッドシート側でアクセスに必要な認証情報を作成します。
今回、こちらのサイトを参考にさせていただきました。ありがとうございます。
Google API Consoleにログイン。
割り当てプロジェクトを作成します。
「+プロジェクトを作成」をクリック。
「プロジェクト名」を入力。「作成」をクリック。
左上のメニュー「APIとサービス」から「ライブラリ」を選択。
「Google Drive API」を検索して「有効にする」。
さらに「Google Sheets API」を選択して「有効にする」。
認証情報を作成します。
実体は認証情報が書き込まれたJSONファイルです。
あとでサーバサイド処理で読み込んでGoogleスプレッドシートへの認証を行います。
「認証情報を作成」をクリック。
「使用するAPI」に「Google Sheets API」、「APIを呼び出す場所」に「ウェブサーバー」、「アクセスするデータの種類」に「アプリケーションデータ」、「いいえ、使用していません」を選択して「必要な認証情報」をクリック。
「サービスアカウント名」にわかりやすい名前を入力、「役割」を「Project」から「編集者」を選択、「キーのタイプ」に「JSON」を選択して「次へ」をクリック。
これでサービスアカウントキーのJSONファイルがダウンロードされました。
アクセスするGoogleスプレッドシートを共有設定します。
アクセスしたいGoogleスプレッドシートを開き、「共有」をクリック。
「他のユーザーとの共有」ダイアログの「ユーザー」欄にダウンロードしたJSONファイルの「client_email」のメールアドレスを入力します。
このメールアドレスは実在はせず、スプレッドシートを共有した相手を識別するためのIDのようです。
鍵の神「ビンツ」
さて、認証情報をサーバサイド処理に取り込みます。
ダウンロードしたJSONファイルをCloud9にアップロードします。
画面左部にドラッグ&ドロップ。
先ほどの参考サイトをもとにソースを変えてみます。
JSONファイルを使って認証したあとに特定の名前のスプレッドシートの1シート目のシート名を表示するプログラムです。
import os import sys sys.path.append(os.path.join(os.path.dirname(__file__), '../site-packages')) import datetime import json import gspread from oauth2client.service_account import ServiceAccountCredentials def lambda_handler(event, context): scope = ['https://www.googleapis.com/auth/drive'] credentials = ServiceAccountCredentials.from_json_keyfile_name('./Shuffle Playism Project-e8939d859c3b.json', scope) gclient = gspread.authorize(credentials) spreadsheet = gclient.open('シャッフル再生教') worksheet = spreadsheet.sheet1 return { 'statusCode': 200, 'body': json.dumps('WorkSheet name is ' + worksheet.title + ' at ' + str(datetime.datetime.now())) }
インポートしているgspreadはGoogleスプレッドシートAPI、oauth2clientはOAuth認証のパッケージです。
これらパッケージをPythonにインストールしておかないとUnable to import
エラーが出ます。
ローカルPCならOSのパスが通っているpip
コマンドを打てばいいのですが、Lambda関数だとウィザードが作成したvenvフォルダ配下にあるpip
コマンドでインストールする必要があるようです。
※嘘でした。普通のpip3.6で問題ありません。コマンドを修正しましたが、キャプチャはそのままです。(2019/12/14)
Lambda関数フォルダの並びに「site-packages」フォルダを作ってそこにインストールしてみます。
cd server pip3.6 install gspread oauth2client -t site-packages
インストールしたパッケージを読み込むためにソースの先頭で「site-packages」フォルダにパスを通します。
import os import sys sys.path.append(os.path.join(os.path.dirname(__file__), '../site-packages'))
「Lambda(local)」で実行してみます。
「API Gateway(local)」よりエラーの詳細が分かって便利です。
んーFileNotFoundError
ですね。ファイルが読み込めていないようです。
どうもLambdaは.py
拡張子以外のファイルを自由に扱えないようです。
セキュリティ上、JSONファイルをS3やSecrets Managerに配備しておいてLambda実行時に取得するのがセオリーなのかもしれません。
破壊の神「ゴーザ」
「セオリーなど打ち壊してくれる!.py
ファイルにしてしまえばよかろう!」
…
JSONファイルをsettings.py
というファイル名に変更し、内容の先頭に
ACCOUNT_KEY =
と付与しました。これでPythonのディクショナリ型宣言になります。
これをlambda_function.py
でインポートします。
sys.path.append(os.path.join(os.path.dirname(__file__), '.')) import settings
また、認証情報作成部分のメソッド名をfrom_json_keyfile_name
からfrom_json_keyfile_dict
に、第1引数をファイルパスからsettings.py
で定義したキー定数に変更します。
credentials = ServiceAccountCredentials.from_json_keyfile_dict(settings.ACCOUNT_KEY, scope)
「Run」。
今度はちゃんとワークシート名「lifes」が取れました。
認証情報をソースとして扱っているのが不安ですが…
「よかろうなのだ!」
…では、セキュリティ情報はまとめてS3かSecrets Managerで管理する、をバックログに積んでおきましょう。
「誰かにお前は神かって聞かれたら、イエスって答えるもんだぜ」
快適コーディングライフのためにもうひと工夫してみましょう。
Cloud9ではデフォルトでPythonの自動フォーマットが利きません。
ので、自動フォーマッタパッケージ「yapf」を入れます。
こちらを参考にさせていただだきました。ありがとうございます。
またpipでインストールしていくわけですが、フォーマッタはLambda関数とか関係なくCloud9のインスタンス上で操作するので、通常のpipでインストールします。
画面下部のターミナルウィンドウで以下を実行。
まずpipをアップグレードしてからyapfをインストールして、試しにフォーマットしてみています。
cd (Lambdaアプリケーション名) sudo python3.6 -m pip install --upgrade pip sudo python3.6 -m pip install yapf yapf -i (Lambda関数名)/lambda_function.py
お、きれいに改行が入っています。
保存時に自動でフォーマットする設定は「AWS Cloud9」から「Preferences」を選択。
「Python Support」の「Format Code on Save」をON、「Custom Code Formatter」を「yapf -i "$file"」と入力します。
これでソースを保存するたびに
こうじゃ!
あー気持ちいい。
次回はお待ちかね、サーバサイド処理を本格的に実装していきます。