AWS Lambdaでunable to import module no module named 'requests'

Q. requestsはどうやってimportするの? A. importしたpythonディレクトリをzipでレイヤーに追加しよう

今回はrequestsがimportできていなさそうです。多少Pythonをやっていればpip install requestsとかpipenv install requestsとかすれば良いと思うかも知れません。今回はAWS Lambdaなので、どこでpip install requestsするんでしょう。わからないので調べます。

「requests python lambda」で検索し、【Lambda】import requests が使えるようにする【python】 - Qiitaを見つけます。レイヤーファイルというものが必要らしいです。読み進めると「例えば、amazon linux2で作業する場合は…」と書いてあります。私は違うので更に「requests python lambda」で検索して【AWS】LambdaにrequestsライブラリをLayerで追加する | SEのプログラミングと英語の勉強ブログを見つけます。 ターミナルで

mkdir python
pip install -t python requests
zip -r9 layer.zip python

と実行します(怪しくなさそうなコマンドだと少しは確認しました。例えばr9オプションは圧縮率です)。

続いて【AWS】LambdaにrequestsライブラリをLayerで追加する | SEのプログラミングと英語の勉強ブログにあるとおり、左のカラムから[レイヤー]を選んで作成します。そういえばさっき料金を気にしたときにx86で動いているみたいな設定を見たので、互換性のあるアーキテクチャにはx86_64を選んでおきました。

作成できたら、バージョン ARNというものが表示されていますね。Lambdaのページを開き、ページ下部のレイヤーからレイヤーの追加を選び、「ARNを指定」を選んで先ほどのARN(バージョン ARN)を入力します。レイヤーを追加しました。

今度こそ…エラーがまた起きています。

しかも12 msも課金されてしまいました(まだ0.001円もかかってなさそうだけど一応確認)。

Q. post_message() takes 0 positional arguments but 2 were given エラーをどうやって解消するの? A. ハンドラの関数で2つ受け取ろう

英語とは言え、エラーメッセージが直接的でわかりやすいですね。post_messageはなんの引数も受け取らない設計なのに、2つの引数が与えられているようです。AWS Lambdaが渡してきているとは言え、単にPythonのエラーのようですね。

ともかくエラーが出たので読めるとは言えエラーメッセージで検索します。「aws lambda takes 0 positional arguments but 2 were given」と検索すると、Error when I'm invoking an AWS lambda, using python. Error: positional arguments but 2 were given - Stack Overflowが見つかりました。私と同じように引数がない関数をハンドラにしていると起きるようです(エラーメッセージ通り)。

公式ガイドラインを読めとのことなので、リンクを開き、日本語版かつPythonのページであるPython の Lambda 関数ハンドラー - AWS Lambdaを開くと、「Lambda が関数ハンドラーを呼び出すと、Lambda ランタイムが 2 つの引数を関数ハンドラーに渡します。」と書いてあります。イベントオブジェクトと、コンテキストオブジェクトがあるようですが、ざっと見た感じ今回使わなくても良さそうです。とはいえ受け取らないとエラーになるので受け取るだけ受け取ります。

import requests
url = "https://slack.com/api/chat.postMessage"
token = "xoxb-xxxxxxxxxxxxx-xxxxxxxxxxxxx-xxxxxxxxxx..."# tokenを入れてください

header={
    "Authorization": "Bearer {}".format(token)
}

data  = {
    "channel" : "C0123456789",# Conversation IDを入れてください
    "text" : "Hello World!"
    }

def post_message(event, context):  # ここで一応受け取っている。使わないけど。
    requests.post(url, headers=header, data=data)

さてまたzipに圧縮してlambdaにアップロードします。

そして橙色のTestボタンを押すと…

Slack「スッコココ!」ついに、lambdaからSlackへ投稿できました。Billed Duration: 350 msはちょっと気になりますが、とはいえやはり1円もかかっていないです。よっぽど私がクリックする1秒の方が価値がありそう。

次の記事では、このプログラムを定期的に実行できるようにしましょう。

© 2019- estie, inc.