全般

[Python] 相対パスを使ってimportする方法

今回は、Pythonで相対パスを使ってimportする方法についてご紹介します。

Pythonで相対パスを使ったimportを行うことで、パッケージ内のモジュール同士の関係を簡潔に記述できます。

パッケージ名が変わった場合にも修正箇所を最小限に抑えられるなど、多くのメリットが存在します。

ただし、実行環境やパッケージ構造を正しく理解していないと、思わぬエラーが発生することもあります。

相対インポートとは

相対インポートとは、現在のパッケージ構造を基準にして、モジュールを読み込む方法です。

.」は現在のパッケージを、「..」は一段階上のパッケージを示します。

これにより、同じパッケージ内や上位階層のモジュールを指定できます。

相対インポートの大きな利点は、モジュール同士の依存関係が明確になり、フォルダ名やパッケージ名を変更した際の影響範囲を小さくできることです。

基本的な使い方

相対インポートでよく使われるパターンは、以下の2種類です。

  • 同一パッケージにあるモジュールをインポート(.
  • 上位パッケージにあるモジュールをインポート(..

同一パッケージからのインポート

同一パッケージのモジュールを利用する場合、先頭に「.」を付けます。

例えば、同じディレクトリにあるmodule_a.pyからsome_functionをインポートするときは、以下のように記述します。

上位パッケージからのインポート

一段階上のパッケージ、またはそれ以上の階層にあるモジュールを読み込みたい場合は、ドットの数を増やします。

例として、一段階上にあるmodule_a.pyからsome_functionをインポートする場合は、以下のように書きます。

具体例

ここでは、単一パッケージ内と複数階層のパッケージ構造を例に解説します。

単一パッケージ内での相対インポート

以下のようなディレクトリ構造を想定します。

  • myproject/
    • mypackage/
      • __init__.py
      • module_a.py
      • module_b.py

まず、module_a.pyを以下のように定義するとします。

そして、module_b.pyでは同じパッケージ内のmodule_aからgreet関数を相対インポートして利用します。

このmodule_b.pyを実行すると、以下のような結果が得られます。

実行結果

Running module_b…
Hello from module_a!

複数階層のパッケージ内での相対インポート

次に、mypackageディレクトリの下にさらにsubpackageというディレクトリを用意した構造を考えます。

  • myproject/
    • mypackage/
      • __init__.py
      • module_a.py
      • subpackage/
        • __init__.py
        • module_c.py

親パッケージのmodule_a.pyにwelcome関数があるとします。

子ディレクトリのmodule_c.pyで、このwelcome関数を相対インポートする例は以下のとおりです。

ただし、直接python module_c.pyと実行すると、相対インポートがうまく機能しない場合があります。

正しく動かすには、プロジェクトのルートディレクトリ(myproject)から以下のコマンドを実行してください。

よくあるエラーと注意点

相対インポートには、いくつか注意するポイントがあります。

  • トップレベルからの実行

    相対インポートはパッケージの一部として実行される場合にのみ機能します。

    スクリプトとして直接実行すると、ValueErrorやImportErrorが発生することがあります。

  • __init__.pyが必要

    Pythonでは、ディレクトリをパッケージとして認識させるために__init__.pyを配置します。

    このファイルがないと、相対インポートが正常に動作しない場合があります。

  • 可読性への配慮

    ドットの数が多い相対インポートを乱用すると、どの階層を参照しているのかが分かりづらくなることがあります。

    必要に応じて絶対インポートとの併用を検討してください。

  • Pythonバージョン

    Python 3以降では相対インポートの仕様が明確ですが、古いバージョンでは挙動が異なる場合があります。

    できるだけ新しいバージョンのPythonを使用すると安全です。

まとめ

相対インポートを活用すると、パッケージ内の依存関係を明確にしつつ、メンテナンス性を高めることができます。

実行環境を整え、パッケージの階層構造を正しく把握しておくと、エラーを防ぎやすくなります。

状況に応じて絶対インポートとの使い分けを検討しながら運用してみてください。