Python自習O0o0 クラスを動的に読み込もうぜ(^~^)

O_9o0 以前の記事

📖 Python自習O_9o0 目次だぜ(^~^) - 目次

O0o0 今回の記事

202101__character__31--ramen-tabero-futsu2.png
「 Python でクラスを動的に読み込むの、どうやるんだぜ?」

📖 How to Dynamically Load Modules or Classes in Python
📖 How to dynamically load a Python class

202101__character__28--kifuwarabe-futsu.png
「 👆 ググれだぜ」

202108__character__12--ohkina-hiyoko-futsu2.png
「 いろんな記事があって どれがベストプラクティスか分かんないのよね」

O1o0 クラスの静的インポート

202101__character__31--ramen-tabero-futsu2.png
「 まず ふつうにクラスをロードしてみようぜ。
👇 以下のファイルを作成してくれだぜ」

    └── 📂 src
        └── 📂 hello
👉          └── 📄 __init__.py
class Hello:
    def __init__():
        pass

    @classmethod
    @property
    def message(clazz):
        return "Hello, world!!"

202101__character__31--ramen-tabero-futsu2.png
「 次に
👇 以下のファイルを作成してくれだぜ」

    ├── 📂 src
    │   └── 📂 hello
    │       └── 📄 __init__.py
    └── 📂 tests
👉      └── 📄 hello_test.py
"""
python -m tests.hello_test
"""
from src.hello import Hello

print(Hello.message)

202101__character__31--ramen-tabero-futsu2.png
「 じゃあ
👇 以下のコマンドを打鍵してくれだぜ」

Input:

python -m tests.hello_test

Output:

Hello, world!!

202101__character__31--ramen-tabero-futsu2.png
「 これが よくやるクラスのロードだぜ」

202101__character__28--kifuwarabe-futsu.png
「 これだと from src.hello import Hello と、クラスの名前が埋め込んであるから、このクラスを読み込むな」

O2o0 クラスの動的インポート

202108__character__12--ohkina-hiyoko-futsu2.png
「 そのファイルか、クラスの名前を コマンドラインから指定したいのよ。
例えば」

python -m tests.hello_test src.welcome

202108__character__12--ohkina-hiyoko-futsu2.png
「 👆 みたいな感じにできないの?」

202101__character__28--kifuwarabe-futsu.png
「 from ~ import 文の名前ストラクチャーを教えてくれだぜ」

from src.hello import Hello
     ---------        -----
     1                2
1. module name
2. class name

202101__character__31--ramen-tabero-futsu2.png
「 👆 これが代表的な例だぜ。こうじゃないケースもあるが今は省くぜ」

202101__character__28--kifuwarabe-futsu.png
「 じゃあ」

obj = load( module_name, class_name)

202101__character__28--kifuwarabe-futsu.png
「 👆 こんな感じで クラスのインスタンスを取得できる関数が作れればいいわけかだぜ」

202101__character__31--ramen-tabero-futsu2.png
「 👇 サンプルコードを真似ようぜ。
以下のファイルを作成してくれだぜ」

    ├── 📂 src
    │   ├── 📂 dimport
👉  │   │   └── 📄 __init__.py
    │   └── 📂 hello
    │      └── 📄 __init__.py
    └── 📂 tests
        └── 📄 hello_test.py
"""
📖 [How to Dynamically Load Modules or Classes in Python](https://www.geeksforgeeks.org/how-to-dynamically-load-modules-or-classes-in-python/)  
📖 [How to dynamically load a Python class](https://stackoverflow.com/questions/547829/how-to-dynamically-load-a-python-class)  
"""


class Dimport:
    @staticmethod
    def load(module_name, class_name):
        # __import__ method used
        # to fetch module
        module = Dimport.load_module(module_name)

        # getting attribute by
        # getattr() method
        return getattr(module, class_name)

    @staticmethod
    def load_module(name):
        components = name.split('.')
        mod = __import__(components[0])
        for comp in components[1:]:
            mod = getattr(mod, comp)

        return mod

202101__character__31--ramen-tabero-futsu2.png
「 👇 サンプルコードを真似ようぜ。
以下のファイルを作成してくれだぜ」

    ├── 📂 src
    │   ├── 📂 dimport
    │   │   └── 📄 __init__.py
    │   └── 📂 hello
    │      └── 📄 __init__.py
    └── 📂 tests
👉      ├── 📄 dimport_test.py
        └── 📄 hello_test.py
"""
python -m tests.dimport_test
"""
from src.dimport import Dimport

print(Dimport.load("src.hello", "Hello").message)

202101__character__31--ramen-tabero-futsu2.png
「 👇 以下のコマンドを打鍵してくれだぜ」

Input:

python -m tests.dimport_test

Output:

AttributeError: module 'src' has no attribute 'hello'

202101__character__28--kifuwarabe-futsu.png
「 👆 srchello なんか持ってない、というエラーが出たぜ」

202101__character__31--ramen-tabero-futsu2.png
「 動的にインポートするときは ディレクトリーを自動で検索してくれないのか。じゃあ 手動で設定しようぜ」

202101__character__31--ramen-tabero-futsu2.png
「 👇 以下のファイルを作成してくれだぜ」

    ├── 📂 src
    │   ├── 📂 dimport
    │   │   └── 📄 __init__.py
    │   ├── 📂 hello
    │   │  └── 📄 __init__.py
👉  │   └── 📄 __init__.py
    └── 📂 tests
        ├── 📄 dimport_test.py
        └── 📄 hello_test.py
from .hello import Hello

202101__character__31--ramen-tabero-futsu2.png
「 👆 src が何を持ってるか 書いてやればいいわけだぜ」

Input:

python -m tests.dimport_test

Output:

Hello, world!!

202108__character__12--ohkina-hiyoko-futsu2.png
「 👆 クラスの動的読取はできそうね」

O3o0 コマンドライン引数に対応

202101__character__31--ramen-tabero-futsu2.png
「 👇 以下のファイルを作成してくれだぜ」

    ├── 📂 src
    │   ├── 📂 dimport
    │   │   └── 📄 __init__.py
    │   ├── 📂 hello
    │   │  └── 📄 __init__.py
    │   └── 📄 __init__.py
    └── 📂 tests
        ├── 📄 dimport_test.py
👉      ├── 📄 dimport_test2.py
        └── 📄 hello_test.py
"""
python -m tests.dimport_test2 -m src.hello -c Hello
"""
import argparse
from src.dimport import Dimport

# Command line arguments
ap = argparse.ArgumentParser()
ap.add_argument('-m', help='module')
ap.add_argument('-c', help='class')
args = ap.parse_args()

print(Dimport.load(args.m, args.c).message)

202101__character__31--ramen-tabero-futsu2.png
「 👇 以下のコマンドを打鍵してくれだぜ」

Input:

python -m tests.dimport_test2 -m src.hello -c Hello

Output:

Hello, world!!

202101__character__31--ramen-tabero-futsu2.png
「 👆 でけたな」

次の記事

📖 Python自習O1o0 Non-numeric Separated Value

関連する記事

📖 Python自習O_9o0 目次だぜ(^~^)

おわり

ツイッターでシェア
みんなに共有、忘れないようにメモ

むずでょ@きふわらべ第29回世界コンピューター将棋選手権一次予選36位

光速のアカウント凍結されちゃったんで……。ゲームプログラムを独習中なんだぜ☆電王戦IIに出た棋士もコンピューターもみんな好きだぜ☆▲(パソコン将棋)WCSC29一次予選36位、SDT5予選42位▲(パソコン囲碁)AI竜星戦予選16位

Crieitは誰でも投稿できるサービスです。 是非記事の投稿をお願いします。どんな軽い内容でも投稿できます。

また、「こんな記事が読みたいけど見つからない!」という方は是非記事投稿リクエストボードへ!

有料記事を販売できるようになりました!

こじんまりと作業ログやメモ、進捗を書き残しておきたい方はボード機能をご利用ください。
ボードとは?

コメント