相対importを使ったPythonファイルをPyCharm上で実行しようとして、うまく動かないって経験ありませんか?
TL;DR
- Program:
$ModuleSdkPath$
- Parameters:
-c "import os,runpy;runpy.run_module('.'.join(r'$FilePathRelativeToSourcepath$'.replace(os.sep,'.').split('.')[:-1]),{},__name__,1)"
- Working directory:
$Sourcepath$
Sources Rootを適切に設定したうえで、上の設定でExternal Toolsを追加してください。
解決したい問題
例えば、my_pkg
という自作のパッケージ内で下のようなファイルを作ります。
x = 42
from .foo import x
if __name__ == '__main__':
print(x)
ここで my_pkg/bar.py をPyCharmで開いて単純に Run すると以下のような例外が発生します。
/usr/bin/python3 /tmp/my_pkg/bar.py
Traceback (most recent call last):
File "/tmp/my_pkg/bar.py", line 1, in <module>
from .foo import x
ModuleNotFoundError: No module named '__main__.foo'; '__main__' is not a package
Process finished with exit code 1
原因
理由については、こちら の記事などで詳しく説明されています。
結論だけ言えば、-m
オプションをつけて、モジュールの完全修飾名 (my_pkg.bar
) を指定して実行するとうまく動きます。
# ERROR!!
/usr/bin/python3 /tmp/my_pkg/bar.py
# OK
cd /tmp
/usr/bin/python3 -m my_pkg.bar
つまり、どうにかしてPyCharmに-m
オプション形式で実行させれば良いわけです。
解決策 1. 愚直に Edit Configuration settings する
下の画像のように設定すると-m
オプション形式で実行させることができます。
しかしこの方法には、実行したいファイルごとに毎回この設定をしなければならない という極めて深刻な問題があります。
解決策 2. External Tools を使う
PyCharm には、外部の実行ファイルを扱う機能が備わっているので、これを利用します。
少し面倒ですが、一度設定するだけで全てのプロジェクトで使えるようになるのが利点です。
External Tools の新規作成
メニューバーの File → Settings → Tools → External Tools と進んで新しい External Tools を追加してください。
Tool settingsの部分は以下のように設定してください。
- Program:
$ModuleSdkPath$
- Parameters:
-c "import os,runpy;runpy.run_module('.'.join(r'$FilePathRelativeToSourcepath$'.replace(os.sep,'.').split('.')[:-1]),{},__name__,1)"
- Working directory:
$Sourcepath$
Sources Rootの設定
あとは my_pkg
の親ディレクトリを右クリックして、Sources Rootとして登録すればOKです。
実行
bar.py
を開いた状態で、メニューバーの Tool → External Tools → python -m をクリックしてください。
きちんと実行できたら成功です。頻繁に使うようであれば、ショートカットキーを割り当てておくと便利です。