PythonでS3上の自作モジュールをスクリプト中で動的にインポートしてみる

2023.03.07

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

はじめに

データアナリティクス事業本部のkobayashiです。

Pythonの自作モジュールを使う際にPythonの実行環境の制約によりあらかじめ自作モジュールを実行環境へ置いておくことができなかったり、パッケージにしてpipでインストールできない場面において、S3上に自作モジュールをアップロードしてその自作モジュールをスクリプト中でインポートする方法を調べたのでまとめます。

S3上のファイルをモジュールとして読み込む

S3上のファイルを読み込む方法を色々調べましたがなかなか最適解が見つからず同じような情報としては以下の記事しか見つかりませんでした。

上記の情報を参考にちょっと回りくどいのですが以下のアプローチで実現しました。

  1. tempfileモジュールで一時ディレクトリを作成する
  2. 一時ディレクトリをsys.path.appendでパスを通す
  3. S3からBoto3で自作のモジュールを一時ディレクトリにダウンロードする
  4. importlibでモジュールを動的にインポートする

コードの解説と動的インポートの実行

では実際に自作モジュールを作成してからS3にアップロードして実行時に読み込んみます。

はじめにモジュールファイルは以下のように四則を行う関数としています。

mymodule.py

def add(x, y):
    return x + y


def sub(x, y):
    return x - y


def mul(x, y):
    return x * y


def div(x, y):
    return x / y

これを予めS3にアップロードしておきます。

次に今回のメインテーマであるS3上の自作モジュールを読み込んで使用するスクリプトは以下のようになります。

main.py

import importlib
import sys
import tempfile

import boto3

s3 = boto3.client("s3")

# 独自モジュール読み込み
with tempfile.TemporaryDirectory(dir="/tmp/", prefix="md_") as tmpdir:
    sys.path.append(tmpdir)
    s3.download_file(
        "my-sample-backet", # バケット名
        "mypackage/mymodule.py", # 自作モジュールのパス
        tmpdir + "/mymodule.py",
    )
    mymodule = importlib.import_module("mymodule")

# モジュールの使用
print(mymodule.add(3, 2))
print(mymodule.sub(3, 2))
print(mymodule.mul(3, 2))
print(mymodule.div(3, 2))

コードを解説します。

  • 1-5行目までは独自モジュールを読み込むために必要なモジュールをインポートしています。
  • 10行目ではtempfileモジュールを使って一時ディレクトリ作成しています。
  • 11行目で一時ディレクトリのパスを通しています。
  • 12-16行目でS3上の独自モジュールを一時ディレクトリにダウンロードします。
  • 17行目でimportlibモジュールを使ってダウンロードしたモジュールをインポートしています。

これでS3上の独自モジュールを読み込んでスクリプト内で実行できるようになります。上記のコードを実行してみると以下のような出力になります。

$  python main.py
5
1
6
1.5

まとめ

S3上にアップロードしたPythonの自作モジュールをスクリプト中でインポートする方法をまとめました。限られた実行環境での使用となりますが、同じような環境で悩んでいる人がいたら是非参考にしてください。

最後まで読んで頂いてありがとうございました。~~