Python を書くとき、1 つの Python スクリプトに全部書いてしまうと身通しが悪くなるので、 普通はこちらのようにモジュールを分けて書いていくと思います。
# libs/foo.py
class Foo:
def print(self):
print("Foo!")
# main.py
from libs.foo import Foo
f = Foo()
f.print()
コマンドラインから実行すると、こんな感じで実行されます。
D:\Path\To> python main.py
Foo!
D:\Path\To>
ところがこれを UE4 の Python プラグインで実行すると、なぜかエラーになることがあります。
(正確には、Python スクリプトを /Content/Python
の直下に置いている時は動作しますが、それ以外のフォルダに置いている時にエラーになります)
LogPython: Error: Traceback (most recent call last):
LogPython: Error: File "D:/Path/To/main.py", line 1, in <module>
LogPython: Error: from libs.foo import Foo
LogPython: Error: ModuleNotFoundError: No module named 'libs.foo'
なんでやねん! UE4 で Python のツールを書き出した時はこの問題が解決できず、あきらめて全機能を 1 つの Python スクリプトの中に書いていました…。
だいぶ後になってわかったのですが、以下のように書けば動きます。 インクルードパスに、実行対象の Python スクリプトが置かれているフォルダを追加します。
# main.py
import sys
import os
sys.path.append(os.path.dirname(__file__)) # この行を追加
from libs.foo import Foo
f = Foo()
f.print()
めでたしめでたし…とは行きません。Python を書くのに VSCode をお使いの方には凄まじいトラップがあります。
フォーマッタ autopep8 を入れますか?とお勧めしてくるので言われるがままにインストールしてしまうと、
# main.py
from libs.foo import Foo
import sys
import os
sys.path.append(os.path.dirname(__file__))
:
こんな感じで勝手に順序を入れ替えてしまい、動かなくなります。 (autopep8 はダメですが、ついでにお勧めされる black, yapf では問題ありません)
ということで、無事 UE4 の Python でもモジュールが使えることがわかりました。
また、モジュール構成を変えた時はソースに問題がなくても No module named '...'
の
エラーが出ることがあります。
逆に、明らかにモジュールが解決できない状況でもエラーが出ないことがあり、頭を悩ませることがあります。
そういうときは、UE4 のエディタをいったん終了し、再実行しましょう。
ちゃんと追い切れてないんですが、どうも前回のモジュール解決情報が残っているようです…。
上記は UE4.26(Python3.7)で確認しました。UE4.25 以前(Python2.7)では、
上記構成に加えて libs/__init__.py
というファイル名で空ファイルを作っておく必要があります。