当サイトは、アフィリエイト広告を利用しています
pythonで開発を始めて最初らへんによくモジュールのimportエラーに
引っかかった。
調べると「PYTHONPATHが~」的なことを言われるので
「PYTHONPATH」について調べてまとめておく
PYTHONPATHは、Pythonが
探すときの検索パスを追加で指定する環境変数のこと。
importしているモジュールを検索する時に使用される
モジュールはpyファイルのこと。
Pythoスクリプトとも呼ばれる
パッケージとは 複数のモジュールをまとめた__init__.py ファイルが含まれるディレクトリのこと。 パッケージはディレクトリ単位でimportできる
モジュールでimportをするとき、Pythonは次の順番でモジュールを探す
PYTHONPATHはこの「4番目」にあたり、標準の検索パスに自分の好きなディレクトリを追加できる。
※当記事ではPYTHONPATHをメインで解説するため、上記の1~5のうち2,3,5は割愛する
例えば
my_project/├── src/│ └── utils.py└── main.py
のようなプロジェクト構成で
def greet() -> str:return "Hello, world!"
from src.utils import greetdef main() -> None:print(greet())if __name__ == "__main__":main()
のようなモジュールの場合
検索の流れ(python main.pyをmy_projectで実行)としては
のようになる。
my_projectで実行
$ python main.pyHello, world!
このプロジェクト構成ではsrc配下に__init__.pyがなくても
パッケージとして認識されているので
from src.utils import greet
の形でimportできてる。
Python 3.3以降では、PEP 420 によって「namespace package(名前空間パッケージ)」という仕組みが導入されたため
__init__.pyがなくてもディレクトリをパッケージとして扱えるようになっている。
※実務では __init__.pyを置いておくのがベター。
同じディレクトリ構成で、PYTHONPATHを指定することでimportに
起点からフルパスを書かなくても実行するようにできる。
def greet() -> str:return "Hello, world!"
from utils import greetdef main() -> None:print(greet())if __name__ == "__main__":main()
のようなモジュールで、PYTHONPATHに下記を指定した場合
PYTHONPATH=./src
検索の流れ(同じく my_project で実行)としては
のようになる
my_projectで実行
$ PYTHONPATH=./src python main.pyHello, world!
もしくは
$ export PYTHONPATH=./src$ echo $PYTHONPATH./srclunaj@TABLET-FGJE15R7 MINGW64 /c/develop/01_TechSamples/Python/PythonOrg/my_project$ python main.pyHello, world!
Python インタプリタが「スクリプトがあるディレクトリ (my_project)」を探索するとき、
その直下のみがモジュール検索対象になります。
つまり
したがってsrcを探索対象にしたい場合は
のいずれかが必要になる
PYTHONPATHを複数設定することもできる。
my_project/├── src/├── lib/├── common/└── main.py
この場合、main.py から src, lib, common のモジュールを使いたければ、
それぞれを下記のようにPYTHONPATHに追加する必要がある。
PYTHONPATH=./src:./lib:./common
あまり使うことはなさそうだが。。。。