Python 3.8ランタイムで動かしていたAWS Lambda関数でエラーが出たので対応した際のメモ。
一年後の自分に向けて。
[OSError: Cannot load native module]
AWS Lambdaがエラーを吐いて、CloudWatch Logsにこんなエラーメッセージが出ていた。
[ERROR] OSError: Cannot load native module 'Crypto.Hash._MD5': Trying '_MD5.cpython-38-x86_64-linux-gnu.so': /var/task/vendor/Crypto/Util/../Hash/_MD5.cpython-38-x86_64-linux-gnu.so: cannot open shared object file: No such file or directory, Trying '_MD5.abi3.so': /var/task/vendor/Crypto/Util/../Hash/_MD5.abi3.so: cannot open shared object file: No such file or directory, Trying '_MD5.so': /var/task/vendor/Crypto/Util/../Hash/_MD5.so: cannot open shared object file: No such file or directory Traceback (most recent call last): File "/var/lang/lib/python3.8/imp.py", line 234, in load_module return load_source(name, filename, file) File "/var/lang/lib/python3.8/imp.py", line 171, in load_source module = _load(spec) File "<frozen importlib._bootstrap>", line 702, in _load File "<frozen importlib._bootstrap>", line 671, in _load_unlocked File "<frozen importlib._bootstrap_external>", line 843, in exec_module File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed File "/var/task/my-lambda-func.py", line 15, in <module> from Crypto.PublicKey import RSA File "/var/task/vendor/Crypto/PublicKey/RSA.py", line 38, in <module> from Crypto.IO import PKCS8, PEM File "/var/task/vendor/Crypto/IO/PKCS8.py", line 44, in <module> from Crypto.IO._PBES import PBES1, PBES2, PbesError File "/var/task/vendor/Crypto/IO/_PBES.py", line 41, in <module> from Crypto.Hash import MD5, SHA1, SHA224, SHA256, SHA384, SHA512 File "/var/task/vendor/Crypto/Hash/MD5.py", line 29, in <module> _raw_md5_lib = load_pycryptodome_raw_lib("Crypto.Hash._MD5", File "/var/task/vendor/Crypto/Util/_raw_api.py", line 300, in load_pycryptodome_raw_lib raise OSError("Cannot load native module '%s': %s" % (name, ", ".join(attempts)))
requirements.txtの記載はこう。
pycryptodome==3.8.2
実際のコードはこんな感じ。
from Crypto.Signature import PKCS1_v1_5 from Crypto.PublicKey import RSA from Crypto.Hash import SHA256
def lambda_handler(event, context):
(略) h = SHA256.new() h.update(plain_text.encode()) signature_scheme = RSA.importKey(key) signer = PKCS1_v1_5.new(signature_scheme) signer.sign(h)
(略)
[原因と対策]
エラーメッセージで検索すると、こちらのスレッドにたどり着いた。
AWS Lambda “Cannot load native module 'Cryptodome.Hash._MD5'”
詳細は自分の遭遇した事象とは違っていそうだが、大筋では同じようだ。
ようするに、C言語で書かれたネイティブモジュールを利用している部分があるせいか、Pythonのバージョンとプラットフォームが同じでないとエラーが出る、ということらしい。
Lambda関数のランタイムを確認すると、Python 3.8を指定していた。ここはエラー発生前から変更されていない。
ビルドとデプロイを行っているパイプラインの直近のログを確認すると、Python 3.9がどうの、というログが目に入った。以前のデプロイのログでは、この部分はPython 3.8と出力されていた。
慌ててパイプラインのソースコードを確認すると、ランタイムのPythonバージョン指定が漏れていた。このズレが原因だろう。
というわけで、Lambda関数を動かすために、Lambda関数のランタイムをPython 3.9に更新したところ、問題なく従前通りに動作した。
Pythonのリリースサイクルを確認したところ、2019年からは毎年新バージョンをリリース、ということになっているようだ。
このままいくと一年後にまた同じことが起きそうだったので、パイプラインのPythonランタイムバージョンも3.9でとりあえず固定しておいた。
1年後くらいに、AWS Lambda関数のPython 3.10ランタイムが使えるようになってたらそれぞれ更新せねば。