Pythonのサブディレクトリ間クラス参照ガイド

概要

Pythonプロジェクトにおいて、異なるサブディレクトリに配置されたクラス間の参照方法について説明します。特に以下のようなディレクトリ構造を持つプロジェクトを想定しています:

project/
├── main.py
├── subdirectory1/
│   ├── __init__.py
│   └── class1.py
└── subdirectory2/
    ├── __init__.py
    └── class2.py

このガイドでは、subdirectory1のクラスをsubdirectory2のクラスが参照し、さらにルートディレクトリのmain.pyからsubdirectory2のクラスを使用する方法を解説します。

詳細

1. パッケージ構造の設定

各サブディレクトリをPythonパッケージとして認識させるために、__init__.pyファイルを配置します。

subdirectory1/init.py

# 空でも構いません
# このファイルの存在によりPythonはディレクトリをパッケージとして認識します

subdirectory2/init.py

# 同様に空でも構いません

2. サブディレクトリ1のクラス定義

subdirectory1/class1.py

class Class1:
    def __init__(self, name):
        self.name = name
    
    def method1(self):
        return f"Class1の{self.name}です"

3. サブディレクトリ2からのクラス参照

サブディレクトリ2のクラスがサブディレクトリ1のクラスを参照するには、相対インポートまたは絶対インポートを使用します。

subdirectory2/class2.py

# 相対インポートの場合(同一プロジェクト内で推奨)
from ..subdirectory1.class1 import Class1
 
# または絶対インポートの場合
# from project.subdirectory1.class1 import Class1
 
class Class2:
    def __init__(self, value):
        self.value = value
        self.class1_instance = Class1("インスタンス")
    
    def method2(self):
        return f"Class2の値は{self.value}で、{self.class1_instance.method1()}"

4. メインファイルからのクラス参照

ルートディレクトリのmain.pyからサブディレクトリ2のクラスを参照するには以下のようにします。

main.py

# カレントディレクトリからの相対パスでインポート
from subdirectory2.class2 import Class2
 
def main():
    # Class2のインスタンスを作成
    obj = Class2("テスト")
    # Class2のメソッドを呼び出す(内部でClass1も使用される)
    result = obj.method2()
    print(result)  # "Class2の値はテストで、Class1のインスタンスです" と表示される
 
if __name__ == "__main__":
    main()

5. 実行時の注意点

プロジェクトを実行する際は、プロジェクトのルートディレクトリから実行します:

python main.py

インポートエラーが発生する場合は、Pythonパスを明示的に設定することも可能です:

# main.pyの先頭に追加
import sys
import os
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
 
from subdirectory2.class2 import Class2

まとめ

Pythonでサブディレクトリ間のクラス参照を行う場合、以下の点に注意することが重要です:

  1. 各サブディレクトリに__init__.pyファイルを配置してパッケージとして認識させる
  2. サブディレクトリ間の参照には相対インポート(from ..module import Class)または絶対インポートを使用する
  3. プロジェクトのルートディレクトリから実行する
  4. 必要に応じてPythonパスを明示的に設定する

これらの方法を適切に使用することで、複雑なプロジェクト構造でも正しくモジュール間の参照を行うことができます。

参考