C#ATIA

↑タイトル詐欺 主にFusion360API 偶にCATIA V5 VBA(絶賛ネタ切れ中)

動的にモジュールをインポートする2

こちらの続きです。
動的にモジュールをインポートする1 - C#ATIA

もうちょっとFusion360スクリプトっぽく考えました。

まず、"hoge.py" "piyo.py" "fuga.py" をそれぞれ作ります。
"hoge.py" の中身はこんな感じです。

# fusion360 API python
# hoge.py

import traceback
import adsk.core
import adsk.fusion
def run(context):
    ui = None
    try:
        app = adsk.core.Application.get()
        ui  = app.userInterface

        app.log('Hello hoge')
    except:
        if ui:
            ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))

残りの2個はそれっぽく察して下さい。

狙いとしては、それぞれのエントリーポイントとなるrun関数を
動的に実行したいのです。

で、結局こんな感じです。

# fusion360 API python

import traceback
import adsk.core
import adsk.fusion
import sys
import pathlib
import importlib
import inspect

# このフォルダーをパスに追加
THIS_DIR = pathlib.Path(__file__).resolve().parent
if str(THIS_DIR) not in sys.path:
    sys.path.append(str(THIS_DIR))

def run(context):
    ui = None
    try:
        app = adsk.core.Application.get()
        ui  = app.userInterface

        # このフォルダ内の自身以外のpyファイルを取得
        files = getPyFileNames()

        for file in files:
            # モジュールとしてインポート
            module = importlib.import_module(file.stem)
            importlib.reload(module)

            # モジュール内から関数名取得
            funcs = [func for func, _ in inspect.getmembers(module, inspect.isfunction)]

            # run関数を持っていたら実行
            if 'run' in funcs:
                module.run(context)

            # モジュールの破棄
            del module

    except:
        if ui:
            ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))

def getPyFileNames() -> list:

    # 同じフォルダ内のpyファイルの取得
    files = [f for f in THIS_DIR.iterdir() if f.is_file() and f.suffix == '.py']

    # 自身は削除
    files.remove(pathlib.Path(__file__).resolve())

    return files

inspectを利用するとクラス名や関数名等が取得出来るのですね。優秀。
run関数を持っていたら、それを実行します。

画像あった方が目につくので、結果はこちら。

あぁCATIAで作ったあのメニューのFusion360版が作れる気がしてきた。
足音が聞こえてきた!