Pythonで1つ上位の階層に存在するディレクトリ内のモジュールからimportする際に発生するエラーと対処法を具体的に説明いたします。
状況
以下のようなディレクトリ構成で、あなたがpkg_bにいるとします。
pkgs
├── pkg_a
│ └── module_a.py (pkg_b/module_b.pyで使用したいfunc_a()が定義されている)
└── pkg_b
└── module_b.py
ここでpkg_b/module_b.pyからpkg_a/module_a.pyの関数func_a()をimportしたいとします。
(加えて、環境変数のPYTHONPATHや.pthファイルなどにインポート対象のパスを追加したくない状況だとします。)
想定されるエラー
pkg_b/module_b.pyのimport文で以下のような記述をすると、それぞれエラーが出る。
(ここではPython3.7.4を想定しています。)
from module_a import func_a
from module_a import func_aでimportしようとした場合に以下のようなエラーが発生する。
ModuleNotFoundError: No module named 'module_a'
from ..pkg_a.module_a import func_a
from ..pkg_a.module_a import func_aでimportしようとした場合に以下のようなエラーが発生する。
ValueError: attempted relative import beyond top-level package
解決法
pkg_b/module_b.pyで以下の記述をするとfunc_a()をimportできるようになる。
import os
import sys
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from pkg_a.module_a import func_a
この書き方だとpkg_bからだけではなくpkgsからmodule_b.pyを実行しても問題無くfunc_a()をimportできます。
余談ですが、この書き方だとPython2.7などのバージョンでは以下のようなエラーが発生します。
ImportError: No module named pkg_a.module_a
その場合の選択肢として、以下のような書き方があります。
import sys
sys.path.append('../pkg_a')
from module_a import func_a
'../pkg_a'でパスを追加しているので、pkgsからmodule_b.pyを実行しようとするとエラーが発生します。くれぐれもご注意ください。
コメント