search
LoginSignup
0

posted at

Lambdaの中からS3のPythonファイルをインポートする

背景・目的

AWSのLambdaをPythonで利用するとき、外部ライブラリをパッケージにまとめてデプロイするのが一般的かと思います。
その場合、パッケージのバージョンは固定されることになるのですが、あるとき、実行時にS3に配置したPythonファイルを実行時に読み込むというケースがあったので、その実現方法について備忘します。

システム構成

S3にアップロードするファイル

下記の内容をs3://some-bucket-name/uploaded_script.pyというパスにアップロードすると仮定します。インポートの挙動を確認するために、少し冗長ですが、標準ライブラリであるjsonをインポートしています。

import json

def hello():
    print(json.dumps({"hello": "world"}))

Lambdaのスクリプト

import_from_s3という関数でS3をインポートする例は下記のようなスクリプトになります。

import json  # Lambdaのスクリプトで使っていなくても、S3側のファイルで必要なのでインポートが必要
import boto3

def split_s3_path(s3_path):
    """
    s3://bucket_name/some/path
    を
    bucket_name, some/path
    に分割する
    """
    parts = s3_path.split("/")
    assert len(parts) >= 4, "S3のパスのパーツがあっていません"
    bucket = parts[2]
    key = "/".join(parts[3:])
    return bucket, key

def get_python_script(s3_client, s3_path):
    bucket, key = split_s3_path(s3_path)
    return s3_client.get_object(Bucket=bucket, Key=key)["Body"].read().decode("utf-8")

def import_from_s3(s3_client, s3_path, module_name):
    """
    S3上にあるpythonファイルからインポートする
    """
    exec(get_python_script(s3_client, s3_path))
    return locals()[module_name]

def handler(event, context):
    s3_client = boto3.client('s3')
    hello_func = import_from_s3(s3_client, "s3://some-bucket-name/uploaded_script.py", "hello")
    hello_func()

これを実行すると、S3側のファイルの関数を実行することができます。

まとめ

今回は、結構レアなケースかと思うのですが、S3上のPythonファイルをインポートできる方法について書きました。
実際に利用される際には、Lambdaのセキュリティ面で穴を一つ増やしてしまうことになるので、ご注意ください。

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
What you can do with signing up
0