LoginSignup
0
0

More than 1 year has passed since last update.

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

Posted at

背景・目的

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のセキュリティ面で穴を一つ増やしてしまうことになるので、ご注意ください。

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