はじめに結論
以下の構成のPythonプロジェクトがあるとします。
├── module1
│ ├── __init__.py
│ ├── filename.py
│ └── program.py
├── main.py
このとき、Pythonモジュール内のプログラムprogram.py
が同モジュール内のfilename.py
を呼び出したいとき
# import filename # “ImportError: No module named” のエラーが出る ①
# import .filename # SyntaxError: invalid syntax のエラーが出る ②
from . import filename # 正解
上記のようにPython3以降では、from . import filename
とする必要があります。
① 絶対パス読み込みではダメな理由
こちらの開発者用公式ガイドに経緯を含めて記述されています。
はじめの要約として
Imports can be ambiguous in the face of packages; within a package, it's not clear whether import foo refers to a module within the package or some module outside the package. (More precisely, a local module or package can shadow another hanging directly off sys.path.)
と理由が端的に説明されています。
つまり、Pythonのモジュールにとって自身内のファイルはsys.path
のパススコープとは別扱いなので、import filename
とするとそのfilenameが、自身の外にある別パッケージにあるもの(sys.path内にあるもの)なのか、自身内のパッケージにあるファイル名なのか、が曖昧なのです。
そのため、Pythonコミュニティのメンバーたちは議論の結果、上述の方針を取ることにしたとのことです。
② 相対パス読み込みがimport .filename
ではダメな理由
こちらの記載によると、
The reason import .foo is prohibited is because after
import XXX.YYY.ZZZ
then
XXX.YYY.ZZZ
is usable in an expression. But
.moduleY
is not usable in an expression.
とあります。
つまり、絶対パス指定では、その後の式(expression)内でそのままの表現で利用できるようにするのがPython3での仕様なので、相対パスだとそれができないから、という理由のことのようです。