できない.dev

Python で「attempted relative import with no known parent package」が解決できない

相対インポートを含むファイルをスクリプトとして直接実行すると、親パッケージを特定できずこのエラーになる。
`python -m パッケージ.モジュール` で実行するか絶対インポートに変える。

#python#import#relative-import#package

公開: 更新:

要約

ImportError: attempted relative import with no known parent package は、相対インポート(先頭がドットの from . import ...)を、パッケージの一部としてではなく単体スクリプトとして実行したときに出ます。
相対インポートはモジュールの __package__ を起点に親パッケージを辿りますが、ファイルを直接実行すると __main__ 扱いになり起点が空になるため、親パッケージを特定できません。python -m でパッケージとして実行するのが基本の解決策です。

ImportError: attempted relative import with no known parent package

よくある原因

  1. スクリプトとして直接実行: python mypkg/main.py のように単体実行すると、そのファイルは __main__ になり相対インポートの基準を失う。
  2. __init__.py が無い: ディレクトリがパッケージとして認識されず、ドット表記の親を辿れない。
  3. 実行位置とパッケージ構成の不一致: プロジェクトルート以外から実行していて sys.path にルートが入っていない。
  4. エントリポイント自身が相対インポートを使っている: 起動ファイルでドット表記を使うと、起動方法によっては必ず失敗する。

解決策

1. -m でパッケージとして実行する

mypkg/main.py を直接叩くのではなく、プロジェクトルートからモジュール指定で実行します。
これで __package__ が正しく設定され、相対インポートが解決します。

# NG: python mypkg/main.py
python -m mypkg.main

ディレクトリ構成の例です。
各パッケージに __init__.py を置きます。

project/
  mypkg/
    __init__.py
    main.py
    utils.py

2. 絶対インポートに書き換える

ドット表記をやめ、パッケージ名から書く絶対インポートにすると、実行方法に左右されにくくなります。

# from .utils import helper  →
from mypkg.utils import helper

3. エントリポイントを分離する

ライブラリ本体は相対インポートのままにし、起動用のファイルをパッケージの外(または python -m mypkg 用の __main__.py)に置いて、そこからパッケージを呼び出す構成にすると安定します。

この記事は役立ちましたか?