9
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Python3.7ランタイムのAWS LambdaでC拡張ライブラリを使用したい!

Last updated at Posted at 2019-12-21

本記事はamazonlinuxでpython3.7を使用したい人、lambda上でpythonのC拡張ライブラリを使用したい人向け。

動機

Python3.7ランタイムのlambda上でscrapyを動かそうとしたところ以下のエラーでうまく実行できなかった。

{
  "errorMessage": "Unable to import module 'spider': cannot import name 'etree' from 'lxml' (/var/task/lxml/__init__.py)",
  "errorType": "Runtime.ImportModuleError"
}

調べたところ、どうやらlxmlライブラリはC言語の拡張を使用しており、そのままではlambdaで使えないとのこと。

諦めればいいものの、Python3にこれから移行していくというタイミングで困ることが多そうなので頑張って解決してみる。

PCはMacを使用。

とりあえずEC2上で動かす

lambdaはサーバレスといっても裏ではamazonlinuxのサーバ上で動くため、とりあえずamazonlinux上で動けばいいのでは?
ということで、早速amazonlinuxのEC2を作成していく。

EC2の作成・ssh接続

ちなみにPython3.7まではamazonlinux、3.8はamazonlinux2上で動くらしい。
AWS Lambda ランタイム

今回はPython3.7を使用するため、amazonlinuxを使用してEC2を作成する。
スクリーンショット 2019-12-16 23.07.41.png
VPCは適当に。

直接SSH接続したいので、パブリックIPを割り当てておく。
また、セキュリティーグループはtype:ssh プロトコル:TCP ポート範囲:22 ソース:自宅のグローバルIP/32あたりで設定しておく。

keypairを作成し、Downloadsフォルダに保存。
その後、~/.sshフォルダにpemファイルを保存。

Downloads $ mv libtestkey.pem ~/.ssh

.ssh $ ls
libtestkey.pem

#秘密鍵として使えるように権限を変更
.ssh $ chmod 600 libtestkey.pem

AwsマネジメントコンソールでEC2のパブリックIPを確認。
スクリーンショット 2019-12-16 23.50.34.png

作成したEC2にsshで接続

$ ssh -i ~/.ssh/libtestkey.pem ec2-user@3.112.178.228
Warning: Permanently added '3.112.178.228' (ECDSA) to the list of known hosts.

       __|  __|_  )
       _|  (     /   Amazon Linux AMI
      ___|\___|___|

https://aws.amazon.com/amazon-linux-ami/2018.03-release-notes/
13 package(s) needed for security, out of 26 available
Run "sudo yum update" to apply all updates.

無事に接続完了。

EC2にpython3.7を導入

ec2
[ec2-user@ip-10-4-0-246 ~]$ yum list | grep python37
$

あれ、、、ない、、、。

ということで、下記サイトを参考にソースファイルからビルドしていく。
CentOS7にPython3.7をインストール(ソースファイルからビルド)

ec2
# yumのアップデート
[ec2-user@ip-10-4-0-246 ~]$ sudo yum clean all
..
[ec2-user@ip-10-4-0-246 ~]$ sudo yum -y update
..
完了しました!

# 必要なパッケージをまとめてインストール
[ec2-user@ip-10-4-0-246 ~]$ sudo yum install zlib-devel libffi-devel bzip2-devel openssl-devel ncurses-devel sqlite-devel readline-devel tk-devel gdbm-devel libuuid-devel xz-devel
..
Is this ok [y/d/N]: y
..
完了しました!

# python3.7.4をダウンロード
[ec2-user@ip-10-4-0-246 ~]$ curl -O https://www.python.org/ftp/python/3.7.4/Python-3.7.4.tgz
..

# 解凍してディレクトリへ移動
[ec2-user@ip-10-4-0-246 ~]$ tar xf Python-3.7.4.tgz
[ec2-user@ip-10-4-0-246 ~]$ cd Python-3.7.4/

# コンパイルしてインストール
[ec2-user@ip-10-4-0-246 Python-3.7.4]$ ./configure --enable-optimizations
..
configure: error: in `/home/ec2-user/Python-3.7.4':
configure: error: no acceptable C compiler found in $PATH
See `config.log' for more details

なんか怒られた。
C コンパイラが無い?
とりあえずgccを入れてみる。

[ec2-user@ip-10-4-0-246 ~]$sudo yum install gcc
..
y
..
完了しました!

もう一度実行してみる。

[ec2-user@ip-10-4-0-246 Python-3.7.4]$ ./configure --enable-optimizations
..
creating Modules/Setup
creating Modules/Setup.local
creating Makefile

お、できたっぽい。
ビルドしてみる。

# ビルド
[ec2-user@ip-10-4-0-246 Python-3.7.4]$ make

.. # 約20分(めっちゃテストしてた)
make[1]: ディレクトリ '/home/ec2-user/Python-3.7.4' から出ます

# インストール
[ec2-user@ip-10-4-0-246 Python-3.7.4]$ sudo make altinstall
..
Successfully installed pip-19.0.3 setuptools-40.8.0

pathを通してバージョンを確認。

[ec2-user@ip-10-4-0-246 bin]$ export PATH=$PATH:/usr/local/bin

[ec2-user@ip-10-4-0-246 bin]$ python3.7 -V
Python 3.7.4

[ec2-user@ip-10-4-0-246 bin]$ pip3.7 -V
pip 19.0.3 from /usr/local/lib/python3.7/site-packages/pip (python 3.7)

ようやく準備完了。

実際にamazon linux上で動かしてみる

今回はscrapyが依存しているlxmlライブラリを使用してテストしてみる。

lambdaで動かすことを想定し、buildフォルダを作成しその中にtestファイルを作成。

[ec2-user@ip-10-4-0-246 ~]$ mkdir build
[ec2-user@ip-10-4-0-246 ~]$ cd build/
[ec2-user@ip-10-4-0-246 build]$ ls
[ec2-user@ip-10-4-0-246 build]$ vim test.py
build/test.py
from lxml import etree

etree.LXML_VERSION

buildフォルダ内にpip install

# -t . を指定することで現在のフォルダにインストール
[ec2-user@ip-10-4-0-246 build]$ pip3.7 install lxml -t .
..
Successfully installed lxml-4.4.2

# 実行!
[ec2-user@ip-10-4-0-246 build]$ python3.7 test.py
(4, 4, 2, 0)

動いた!

lambdaに乗っけてみる

lambdaデプロイ用に色々作る

ローカルの作業環境にlibtestというフォルダを作成、その後sam initしてテンプレートを作成。


$mkdir libtest
$cd libtest

#ランタイムはpython3.7を指定
libtest $sam init --runtime python3.7
..
[*] Project initialization is now complete

app.pyを編集

sam-app/hello_world/app.py
from lxml import etree

# lambda handler
def lambda_handler(event,context):
    print(etree.LXML_VERSION)

ここで一旦ローカルでpip installするとどうなるか試す

hello_world $pip3 install lxml -t .

テンプレートの修正

sam-app/template.yaml
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: >
  sam-app

  Sample SAM Template for sam-app

# More info about Globals: https://github.com/awslabs/serverless-application-model/blob/master/docs/globals.rst
Globals:
  Function:
    Timeout: 3

Resources:
  HelloWorldFunction:
    Type: AWS::Serverless::Function # More info about Function Resource: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction
    Properties:
      CodeUri: hello_world/
      Handler: app.lambda_handler
      Runtime: python3.7

デプロイ用shellの作成

sam-app/deploy.sh
# バケット名は世界中で一意な任意の名前にする
aws s3 mb s3://rkhcx-libtest-bucket

# デプロイ用パッケージの作成
echo "デプロイ用のパッケージを作成します。"
aws cloudformation package --template-file template.yaml \
--output-template-file output-template.yaml \
--s3-bucket rkhcx-libtest-bucket

# デプロイ
aws cloudformation deploy --template-file output-template.yaml \
--stack-name libtest-stack \
--capabilities CAPABILITY_IAM

デプロイ

sam-app $sh deploy.sh
..
Successfully created/updated stack - libtest-stack

lambdaが作成されたので、テスト実行してみる

スクリーンショット 2019-12-21 23.49.15.png

やはりlxmlが読み込めない模様。

先ほどEC2上でインポートしたlxmlをローカルにコピー

まずはローカルでインポートしたlxmlライブラリを削除。
その後、EC2からlxmlフォルダをscpでコピーしてくる。

hello_world $rm -rf lxml*

hello_world $scp -i ~/.ssh/libtestkey.pem -r ec2-user@3.112.178.228:/home/ec2-user/build/lxml .

再デプロイして実行!

sam-app $sh deploy.sh
..
Successfully created/updated stack - libtest-stack
スクリーンショット 2019-12-22 0.45.34.png

実行できた!

参考文献

CentOS7にPython3.7をインストール(ソースファイルからビルド)

9
2
1

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
9
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?