C#ATIA

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

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

探せば簡単に見つかるお話ですが、今後やろうと思っている事が
ある為、自身の理解の理解を深める為です。

通常、他のpyファイルから、クラスなり関数なりをインポートし
利用するのであれば、簡単です。

まずこのような面白味の一切ない "foo.py" を作成します。

# fusion360 API python
# foo.py

class Foo:
    def hello(self):
        print('hello')

Fooクラス内にはhelloメソッドのみがあります。

これを呼び出す為、同じフォルダ内にFusion360スクリプト
エントリーポイントとなるrun関数をこんな感じで作成すれば
OKです。

# fusion360 API python

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

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

from .foo import Foo

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

        Foo().hello()

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

"何もFusion360APIでやらなくたって・・・" とは感じますが、
検索してHitする内容と違う部分がありました。

通常のpythonの場合は、同じフォルダ内のpyファイルを
インポートする際は何も問題無いのですが、Fusion360の場合は
スクリプト自身のフォルダをsys.pathに追加しなければ、
エラーとなりました。
この辺が大人の事情なのでしょう。


ここからが本題。
このfooをインポートしている

from .foo import Foo

部分を・・何と言いますか、もっと大人な事情な方法で
呼び出しする事が出来ないかな?と思っています。

例えば、事前に "foo" だと分かっていない場合に
何かしらの方法で、文字として取得しモジュールとして
呼び出しできないか? と言う事です。

探した所、importlibなるものが標準ライブラリに
入っている事を知りました。
モジュールの動的読み込み - Qiita
同じような事を考える方々はいらっしゃるものです・・・。

実は、exec関数で強引な方法も試したのですが、グローバルな
部分に記載しなかれば機能しなかったり、あまりに暴力的なので
宜しくないとの事。

run関数をこんな感じで書き換えると、無事機能しました。

# fusion360 API python

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

# このフォルダーをパスに追加
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

        foo = importlib.import_module('foo')
        foo.Foo().hello()

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

メソッド名を調べる事も出来るものが、標準ライブラリに
入っていたのですが何だったかな・・・。