0
0

More than 3 years have passed since last update.

【AWS SAM】sam local invokeの「invalid ELF header」をなんとかする

Last updated at Posted at 2020-03-01

環境

  • MacOSX
  • SAM CLI, version 0.41.0
  • python3.8

下記内容はsam initで作成されたものそのまま使用しています。
違いはrequirements.txtの内容のみです。

現象

以下のような状態でpip installをしてsam local invokeをすると invalid ELF headerが発生する。

$ cat sam-app/hello_world/requirements.txt
requests
pysftp
$ pip install -r requirements.txt  -t ./

$ sam local invoke
Invoking app.lambda_handler (python3.8)
(中略)
{"errorType":"Runtime.ImportModuleError","errorMessage":"Unable to import module 'app': /var/task/bcrypt/_bcrypt.abi3.so: invalid ELF header"}

これについてはモジュールに含まれているバイナリファイルがAmazonLinux2ではないための環境要因とのこと。

Error in AWS Lambda: invalid ELF header #117
https://github.com/Cyan4973/xxHash/issues/117

AmazonLinux2内で実行する、もしくはそこで実行したものを持ってくれば一応は解決すると言う感じっぽい。

ただそのためにEC2を立ち上げるのはやはり面倒な上に(と言うかお金もかかるし)、
記事投稿時点でAnazonLinuxの標準のPythoはPython2なのでその辺もなんとかする必要があり手間が大きい

解決

sam buildを行なって実行すればLambda(AmazonLinux2?)用の環境に作られたライブラリがインストールされる。

$ sam build
Building resource 'HelloWorldFunction'
Running PythonPipBuilder:ResolveDependencies
Running PythonPipBuilder:CopySource

Build Succeeded
(中略)


$ sam local invoke
Invoking app.lambda_handler (python3.8)
(中略)
{"statusCode":200,"body":"{\"message\": \"hello world\"}"}

ただし、buildをした場合は、作成される.aws-sam/buildの方のコードが実行されるので、
毎回buildが必要となりインタプリタ系の言語のお手軽さが失われてしまう。

なので、
.aws-sam/buildにinstallされたモジュールを現在開発しているディレクトリに移動し.aws-sam/buildを削除する。
こうすることで毎回buildする必要がなくbuild前の元の方のコードが実行することができる。

$ ls .aws-sam/build/HelloWorldFunction/
PyNaCl-1.3.0.dist-info              certifi-2019.11.28.dist-info            idna-2.9.dist-info              requests
(以下省略)

$ cp .aws-sam/build/HelloWorldFunction/ ./hello_world/
$ sam local invoke
Invoking app.lambda_handler (python3.8)
(中略)
{"statusCode":200,"body":"{\"message\": \"hello world\"}"}

(未解決)サブディレクトリにモジュールを配置したい

上記の方法ではbuild時にinstallされるモジュールは指定場所直下になるみたいです。
なのでcpの際にはモジュール以外の自分の書いたソースコードも含まれています(上記では取り除いてませんが)
これについてはまだ現時点で解決にたどり着けていません。

.aws-sam/build/から持ってくる際は.libディレクトリを作成してそこにコピー、
以下を記載することでlib配下のモジュールを取ってこれるのでこれで開発中は多少ごちゃごちゃ感がなくなると思います。

sys.path.append("./lib/")
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0