sec05 - 第3章:Pythonのモジュール探索の仕組みを徹底解説:sys.path・sys.modulesの基本

このレクチャーでは、Pythonがimport文を実行するときに「どこを探してモジュールを見つけているのか」を理解します。実は、Pythonはモジュールを探すとき、あらかじめ決められた「検索リスト(探索パス)」の中を順番に調べています。

その「探索リスト」を確認できるのが、sysモジュールの中にあるpathという変数です。これを理解すれば、ModuleNotFoundErrorのようなimportに関するエラーが出たときも、どこを修正すべきか判断しやすくなります。

スポンサーリンク

モジュールの探索順序とは?Pythonのimportが動く仕組み

Pythonがimportを実行するとき、最初にsys.modulesに情報がキャッシュされていないか確認します。

sys.modules は何をしているのか(キャッシュの役割)

sys.modulesはdict型のデータで、モジュールの名前と情報がペアで管理されています。sys.modulesに、モジュールが既に登録されている時は、登録済みのモジュールを使います。

sys.modulesに情報が保持されていなければ、次の順序でモジュールの探索が行われます:

  • ① 「現在のスクリプトのフォルダ」を最初に探す
  • ② 環境変数PYTHONPATHに登録されたフォルダを探す
  • ③ Pythonの標準ライブラリ(libフォルダ)を探す
  • ④ pipで追加された、サードパーティー製パッケージ(site-packages)を探す

この順序は固定されており、Pythonが最初に見つけた同名モジュールを読み込みます。したがって、同じ名前のモジュールが複数の場所にあると、意図しない方がimportされてしまうこともあります。

sys.path でモジュール探索パスを確認する方法

まずは、実際にsys.pathの中身を確認してみましょう。sys.pathはlist型のデータで、Pythonがモジュールを探すディレクトリの一覧が格納されています。

ファイルを新しく作成し、次のコードを実行して確認してみましょう。(実行結果は、OSやPythonのインストール場所、実行フォルダによって異なります。)

import sys
from pprint import pprint

pprint(sys.path)
# 実行結果例 (環境により異なります)
['C:\\Users\\xxx\\Documents\\python101', # 実行中のスクリプトがあるフォルダ (sys.pathの先頭)
 'C:\\Users\\xxx\\AppData\\Local\\Programs\\Python\\Python313\\python313.zip',
 'C:\\Users\\xxx\\AppData\\Local\\Programs\\Python\\Python313\\DLLs',
 'C:\\Users\\xxx\\AppData\\Local\\Programs\\Python\\Python313\\Lib', # 標準ライブラリ
 'C:\\Users\\xxx\\AppData\\Local\\Programs\\Python\\Python313',
 'C:\\Users\\xxx\\AppData\\Local\\Programs\\Python\\Python313\\Lib\\site-packages'] # pipで追加されたパッケージの保存先

上記のlistが、Pythonがモジュールを探す順番そのものです。上から順に探していき、最初に該当するファイルを見つけた時点で探索が止まります。

出力結果の1行目のパスが、現在実行中のスクリプトがあるフォルダになります。2行目以降、設定されていれば『PYTHONPATH』, 次に『標準ライブラリ』, 最後に『pip installで追加されたライブラリの保存先(site-packages)』の順にパスがlistに格納されています。

スポンサーリンク

一時的に探索パスを追加する方法(sys.path.append)

一時的に探索パスを追加するには、sys.pathのlistに対して要素を追加するだけです。ただし、この設定は一時的なもので、Pythonを再起動するとリセットされることに注意してください。

import sys
sys.path.append(r'C:\Users\xxx\Documents\python101\fortune_cookie')

import fortune

もし、他のモジュールからfortuneimportしたい場合(fortune_cookie/までのパスが通っていないとすると)、上記のようにpathを追加することで、fortuneimportすることができるようになります。

まとめ:探索パスを理解すればimportエラーは怖くない

  • Pythonはsys.pathのフォルダを上から順に探索する。
  • sys.path.append()で探索対象を一時的に追加できる。
  • 実行場所とパッケージ構造の関係を理解すれば、import時にエラーが出た時、解決方法を探ることができるようになる。
スポンサーリンク