python3
importlib

python動的モジュールの読み込み

importlibを使うと動的にモジュール(pyファイル)が読めるらしい。
しかし、使い方がさっぱりわからなくてハマったので、メモします。

ファイル一覧

.
├── main.py
└── plugins
    ├── hoge1.py
    ├── hoge2.py

main.pyと同じ階層に「plugins」というディレクトリがあります。
中にはpyファイルがあります。

ソース。

main.py
# -*- coding: utf-8 -*-
import os
import importlib


def main():
    usrsrc = 'plugins'            #後付で追加したいスクリプトをここに入れる。
    plugins_dir = os.listdir(usrsrc)  #pluginsディレクトリのファイル一覧の取得(リスト型)

    current_dir = os.path.dirname(os.path.abspath(__file__)) #実行ファイルのディレクトリパスを取得

    for u_src in plugins_dir:             #ファイル一覧をリスト化する。
         if u_src.endswith('py'):         #拡張子がpyであるかどうかの判断(正規表現:py$)
             print("hit :",u_src)
             path =  usrsrc + '/' + u_src  #ここはpath = plugins/hoge1.pyのようなイメージ
             #print("path :" , path)
             cpath = os.path.splitext(path)[0].replace(os.path.sep, '.')  #path変数の/を.に置きかける。
             print("cpath :" , cpath)
             #cpath = 'plugins.hoge1'
             noge = importlib.import_module(cpath)  #変数nogeにモジュールを代入。
             print(noge)
             noge.hello() #hoge1.pyの中のhello()をコールする。


if __name__ == '__main__':
    main()

plugins/hoge1.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-

test="hoge"
def hello():
    print("test :", test)

def main():
    hello()

if __name__ == '__main__':
    main()
plugins/hoge2.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-

test="hogehoge"
def hello():
    print("test :", test)

def main():
    hello()

if __name__ == '__main__':
    main()

[gitに置いてみました。]
https://github.com/ajitama/importlib-test

実行結果

$ python main.py
hit : hoge2.py
cpath : plugins.hoge2
<module 'plugins.hoge2' from '[実行されたパス]/plugins/hoge2.py'>
test : hogehoge
hit : hoge1.py
cpath : plugins.hoge1
<module 'plugins.hoge1' from '[実行されたパス]/plugins/hoge1.py'>
test : hoge

この関数はplugin配下を全て読み込んで実行してますが
importlib.import_module()の列の前で、分岐をつけてやれば必要なものだけ、読み込むことも可能だと思います。
=同じ関数名でも別のファイルに切り替えて処理内容を自在に切り替えられるってことで。

たったこれだけで3日以上ハマったんで役に立つ日が来ることを期待してます。。