モジュールインポートのルール
Pythonがモジュールをインポートする際、厳格なルールに従ってファイルを検索します。指定されたディレクトリ内のPythonファイル(.py)を探します。
モジュールの検索場所
Pythonは通常、以下の3つの主要な場所を順番に検索します。
- 優先的に、現在実行中のスクリプトと同じディレクトリ(この部分で問題が発生しやすい)
- Pythonのインストールディレクトリ(組み込みモジュール)
- Pythonのインストールディレクトリにあるsite-packages(サードパーティ製モジュール)
カレントディレクトリでのよくある問題
問題1:同名のモジュール
カレントディレクトリに標準ライブラリと同じ名前のモジュールが存在すると、Pythonはそのディレクトリ内のモジュールを優先的に使用し、他のパスは検索しません。
問題2:スクリプトの実行場所
Pythonは、実行されているスクリプトのディレクトリをカレントディレクトリとして扱います。これは、スクリプトを直接実行する場合に特に重要です。
問題3:PyCharmによるsys.pathの自動追加
PyCharmのようなIDEは、プロジェクトのルートディレクトリをsys.pathに自動的に追加する場合があります。そのため、IDE内ではインポートが成功するが、ターミナルから実行すると失敗するという状況が発生することがあります。
問題4:sys.pathの設定
- プロジェクトのルートディレクトリでPyCharmではインポートに成功するが、IDE外では失敗する。
- 他のディレクトリにあるスクリプトから、特定のディレクトリのモジュールをインポートできない。
- 問題の原因が不明な場合は、sys.pathの内容を確認して、現在の検索パスを把握することが有効です。
sys.pathの明示的な追加
Pythonは、sys.pathリストに含まれるディレクトリを順番に検索してモジュールを探します。プロジェクトのルートディレクトリを明示的にsys.pathに追加することで、インポートの問題を解決できます。
以下は、現在のスクリプトの親ディレクトリをsys.pathに追加する例です。この方法は柔軟性が高く推奨されます。
import os
import sys
# 現在のスクリプトの親ディレクトリを取得し、sys.pathに追加
project_root = os.path.dirname(os.path.abspath(__file__))
sys.path.append(project_root)
現在のモジュール検索パスの確認
sys.pathの内容を表示することで、Pythonがどのディレクトリを検索しているかを確認できます。
import sys
print("現在のモジュール検索パス:")
for path in sys.path:
print(f" - {path}")
相対インポートと絶対インポート
Pythonでは、モジュールをインポートする方法に相対インポートと絶対インポートの2種類があります。
# 絶対インポート
import data
from tools import my_module
# 相対インポート(現在のパッケージ内)
from ..database import sqlite_handler
カレントディレクトリ内のモジュールをインポートする際は、絶対パスまたは相対パスのどちらでも使用できます。ドット(.)は現在のディレクトリ、ドット2つ(..)は親ディレクトリを意味します。
ただし、ルートディレクトリから相対パスでインポートすることはできません。
一般的なガイドライン
- メインプログラムから他のモジュールをインポートする場合は、絶対インポートを使用します。
- 同じパッケージ内の他のモジュールをインポートする場合は、相対インポートを使用します。