AWS Lambda (Python 3.12) で使用可能な pandas の Lambda Layer を準備する

Python 3.12 版に書き直しました。他のバージョンでも基本は同じですのでバージョンを読み替えてご利用ください。
2024.1.8

こんにちは、広野です。

データ分析や加工でよく使われるライブラリに、pandas があると思います。AWS Lambda 関数の中でそれを使用したいときには、外部ライブラリとして呼び出せるよう、あらかじめ使用するリージョン内に pandas の Lambda Layer を用意しておかなければなりません。

本記事では、Python 3.12 ベースの AWS Lambda 関数で動作する pandas の Lambda Layer を準備する手順を紹介します。

やりたいこと

  • Python 3.12 ベースの Lambda 関数で動作する pandas の Lambda Layer を準備する。
  • Lambda Layer への登録は AWS CloudFormation を使用する。

実現方法

  • pandas モジュールのインストールは AWS Cloud9 (Amazon Linux 2023) 上で行い、必要ファイルを ZIP で固める。
  • AWS Cloud9 に Python 3.12 をインストールする。
  • pip も最新にアップグレードする。
  • 完成した ZIP ファイルを AWS CloudFormation で Lamda Layer に登録する。

手順

  1. AWS Cloud9 を Amazon Linux 2023 で立ち上げる。
  2. Python 3.12 を pyenv でインストールする。
    以下、必要なコマンド。#はコメントとする。
# 下準備。pythonディレクトリを作成しておく。
mkdir python

# 必要なモジュールをインストール。
sudo yum -y install bzip2-devel xz-devel
# Python環境管理ツール pyenv を Git からインストール。
git clone https://github.com/pyenv/pyenv.git ~/.pyenv

# pyenvのパスを通すよう、.bashrcをviで修正。
vi ~/.bashrc
# 以下追記内容
export PATH="$HOME/.pyenv/bin:$PATH"
eval "$(pyenv init -)"
# 追記内容ここまで

# .bashrcの修正を反映
source ~/.bashrc

# pyenv のバージョンを確認
pyenv --version

# インストール可能なPython3.12のバージョンを確認
pyenv install --list | grep 3.12

# 最新のPython3.12.1をインストール
pyenv install 3.12.1

# Python3.12.1を使用するよう環境を設定
pyenv global 3.12.1

# Pythonのバージョンを確認
python -V

3. pip をアップグレードする。

# アップグレード
pip install --upgrade pip

# アップグレード後バージョン確認
pip -V

4. pandas をインストールする。
執筆時点では、pandas 2.1.4 がインストールされました。

pip install pandas

5. Pandas 関連ファイルを python ディレクトリにコピーし、ZIP 圧縮する。
インストールされているモジュールのバージョンは執筆時点のもの。

cd /home/ec2-user/.pyenv/versions/3.12.1/lib/python3.12/site-packages

cp -r dateutil /home/ec2-user/environment/python/
cp -r numpy /home/ec2-user/environment/python/
cp -r numpy-1.26.3.dist-info /home/ec2-user/environment/python/
cp -r numpy.libs /home/ec2-user/environment/python/
cp -r pandas /home/ec2-user/environment/python/
cp -r pandas-2.1.4.dist-info /home/ec2-user/environment/python/
cp -r python_dateutil-2.8.2.dist-info /home/ec2-user/environment/python/
cp -r pytz /home/ec2-user/environment/python/
cp -r pytz-2023.3.post1.dist-info /home/ec2-user/environment/python/
cp -r six-1.16.0.dist-info /home/ec2-user/environment/python/
cp -r six.py /home/ec2-user/environment/python/
cp -r tzdata /home/ec2-user/environment/python/
cp -r tzdata-2023.4.dist-info /home/ec2-user/environment/python/

cd /home/ec2-user/environment

zip -r pandas214.zip python

Lambda Layer に登録する ZIP ファイル内のディレクトリ構成はランタイムによって決まっている。

そのため、一連のファイルを一旦 python フォルダ内にコピーした後、python フォルダもろとも ZIP 圧縮をかける。

6. 完成した ZIP ファイル pandas214.zip を任意の Amazon S3 バケットにコピーする。(以下は例)

aws s3 cp ./pandas214.zip s3://s3-bucket-name/sdk/Python3.12/

ここまでで、pandas モジュールのファイルは完成。以降 Lambda Layer への登録をする。

AWS CloudFormation テンプレートによる実装

以下、AWS CloudFormation のテンプレートサンプルです。

ここでは、あらかじめ任意の Amazon S3 バケット内に配置した pandas214.zip を Lambda Layer として登録し、その Lambda Layer を関連付けた Lambda 関数を作成しています。

Lambda 関数には、pandas を使用したサンプルコードを載せています。外部から受け取った JSON データを CSV ファイルに変換して Amazon S3 バケットに保存する、というシンプルなコードです。

AWSTemplateFormatVersion: 2010-09-09
Description: The CloudFormation template that creates sample resources for Lambda Layer.

# ------------------------------------------------------------#
# Input Parameters
# ------------------------------------------------------------#
Parameters:
  SystemName:
    Type: String
    Description: The system name.
    Default: example
    MaxLength: 10
    MinLength: 1

  S3BucketNameSdk:
    Type: String
    Description: S3 bucket name where SDKs are uploaded. (e.g. example-sdks-xxxxxx)
    Default: example-sdks-xxxxxx
    MaxLength: 50
    MinLength: 1

  S3KeyPandasSdk:
    Type: String
    Description: S3 key of pandas.zip. Fill the exact key name if you renamed. (e.g. Python3.12/pandas214.zip)
    Default: Python3.12/pandas214.zip
    MaxLength: 50
    MinLength: 1

Resources:
# ------------------------------------------------------------#
# Lambda Layer
# ------------------------------------------------------------#
  LambdaLayerPandas214:
    Type: AWS::Lambda::LayerVersion
    Properties:
      LayerName: !Sub example-pandas-${SystemName}
      Description: !Sub Pandas 2.1.4 for ${SystemName}
      CompatibleRuntimes:
        - python3.12
      Content:
        S3Bucket: !Sub ${S3BucketNameSdk}
        S3Key: !Sub ${S3KeyPandasSdk}
      LicenseInfo: BSD-3-Clause

# ------------------------------------------------------------#
# Lambda Function
# ------------------------------------------------------------#
  LambdaExamplePandas:
    Type: AWS::Lambda::Function
    Properties:
      FunctionName: !Sub example-lambda-with-pandas-${SystemName}
      Description: !Sub Lambda Function example with pandas.
      Runtime: python3.12
      Timeout: 180
      MemorySize: 256
      Role: !GetAtt LambdaExecutionRole.Arn
      Handler: index.lambda_handler
      # pandas の Lambda Layer を関連付ける
      Layers:
        - !Ref LambdaLayerPandas214
      Tags:
        - Key: Cost
          Value: !Sub example-${SystemName}
      Code:
        ZipFile: !Sub |
          import json
          import pandas as pd  # pandas をインポート
          import datetime
          import boto3
          def datetimeconverter(o):
            if isinstance(o, datetime.datetime):
              return str(o)
          def lambda_handler(event, context):
            try:
              # resultはここでは外部から受け取ったJSONデータ。pandasでロード
              df = pd.DataFrame(event['result'])
              # データを一時領域に保存するときのファイル名
              tempFileName = '/tmp/result.csv'
              # JSONデータをCSVファイルに変換
              df.to_csv(tempFileName)
              # CSVファイルをS3にアップロード
              outputBucket = 'example-${SystemName}-result'
              outputS3Key = 'result/result.csv'
              s3 = boto3.resource('s3')
              res = s3.meta.client.upload_file(tempFileName, outputBucket, outputS3Key)
            except Exception as e:
              print(e)
              return {
                "result": str(e)
              }
            else:
              return {
                "result": json.dumps(res, indent=4, default=datetimeconverter)
              }
    DependsOn:
      - LambdaExecutionRole
      - LambdaLayerPandas214

# ------------------------------------------------------------#
# Lambda Execution Role (IAM)
# ------------------------------------------------------------#
  LambdaExecutionRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: !Sub example-S3InvocationRole-${SystemName}
      Description: This role allows Lambda functions to be executed.
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              Service:
              - lambda.amazonaws.com
            Action:
              - sts:AssumeRole
      Path: /
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
        - arn:aws:iam::aws:policy/AmazonS3FullAccess

※ IAM ロールに与える権限は適宜修正ください。

まとめ

いかがでしたでしょうか?

pandas を Lambda Layer に登録する手順を中心に紹介しましたが、登録後にそれらを使用するところまでざっくりとご理解頂けたのではないかと思います。

Lambda Layer はリージョンの範囲で共有されるので、一度登録してしまえば他の Lambda 関数からもすぐに呼出ができます。外部ライブラリを使用した Lambda 関数を作成するには必須の便利機能です。

Lambda Layer は設定により別の AWS アカウントにも共有することができます。世の中には、全世界の人向けに自分が作った多数の Lambda Layer を公開してくれている人がいます。それを利用させてもらうのも手なのですが、自分のサービス維持を見知らぬ他人の(特に個人の)リポジトリに依存するのは気が引けたので、面倒ですが自分で作成しました。

本記事が皆様のお役に立てれば幸いです。

著者について
広野 祐司

AWS サーバーレスアーキテクチャを駆使して社内クラウド人材育成アプリとコンテンツづくりに勤しんでいます。React で SPA を書き始めたら快適すぎて、他の言語には戻れなくなりました。サーバーレス & React 仲間を増やしたいです。AWSは好きですが、それよりもAWSすげー!って気持ちの方が強いです。
取得資格:AWS 認定は12資格、ITサービスマネージャ、ITIL v3 Expert 等
2020 - 2023 Japan AWS Top Engineer 受賞
2022 - 2023 Japan AWS Ambassador 受賞
2023 当社初代フルスタックエンジニア認定
好きなAWSサービス:AWS Amplify / AWS AppSync / Amazon Cognito / AWS Step Functions / AWS CloudFormation

広野 祐司をフォローする
クラウドに強いによるエンジニアブログです。
SCSKは専門性と豊富な実績を活かしたクラウドサービス USiZE(ユーサイズ)を提供しています。
USiZEサービスサイトでは、お客様のDX推進をワンストップで支援するサービスの詳細や導入事例を紹介しています。
AWSアプリケーション開発クラウドソリューション
シェアする
タイトルとURLをコピーしました