Pythonでimportの対象ディレクトリのパスを確認・追加(sys.pathなど)
Pythonのimport文で標準ライブラリやpipでインストールしたパッケージ、自作のパッケージなどをインポートするときに探索されるパス(ディレクトリ)をモジュール検索パス(Module Search Path)と呼ぶ。
自作のパッケージやモジュールをインポートしたい場合は正しく設定しておく必要がある。
ここではimportの対象となるディレクトリのパスであるモジュール検索パスを確認したり新たに追加したりする方法を説明する。
importの基本的な使い方などは以下の記事を参照。
sys.pathでモジュール検索パスを確認
モジュール検索パスは標準ライブラリのsysモジュールのsys.pathに格納されている。
sys.pathはディレクトリのパスを文字列として格納したリストオブジェクトなのでprint()で中身を確認できる。
ここではpprintを使って見やすくしている。
import sys
import pprint
pprint.pprint(sys.path)
これを実行すると以下のような結果が得られる。
pwd
# /Users/mbp/Documents/my-project/python-snippets/notebook
python3 print_sys_path.py
# ['/Users/mbp/Documents/my-project/python-snippets/notebook',
# '/Users/mbp/Documents/lib',
# '/Users/mbp/Documents/my-project/python-snippets/notebook',
# '/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python37.zip',
# '/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7',
# '/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7/lib-dynload',
# '/usr/local/lib/python3.7/site-packages']
結果は環境によって異なるが、例の環境(HomebrewでPython3をインストールしたMac)では、
- スクリプトファイル(
.pyファイル)があるディレクトリ - 環境変数
PYTHONPATHで指定したディレクトリ(後述) - カレントディレクトリ
- 標準ライブラリのためのディレクトリ(3つ)
pipでインストールしたサードパーティライブラリのためのsite-packagesディレクトリ
が格納されている。
ターミナルでカレントディレクトリを移動して再度実行すると、3. カレントディレクトリが変化していることが分かる。
cd ..
pwd
# /Users/mbp/Documents/my-project/python-snippets
python3 notebook/print_sys_path.py
# ['/Users/mbp/Documents/my-project/python-snippets/notebook',
# '/Users/mbp/Documents/lib',
# '/Users/mbp/Documents/my-project/python-snippets',
# '/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python37.zip',
# '/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7',
# '/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7/lib-dynload',
# '/usr/local/lib/python3.7/site-packages']
スクリプトファイルを実行する場所によってインポートがうまくいったりいかなかったりするのは、カレントディレクトリによってモジュール探索パスが変わっているのが原因。
また、sys.pathの先頭から優先してモジュールを探索するため、標準ライブラリと同じ名前のファイルがスクリプトファイルと同じディレクトリにあるとそちらがインポートされる。インポートはされているのに想定の関数などが使えない場合はこれが原因。該当ファイルをリネームするか移動すればよい。
sys.pathにモジュール検索パスを追加
sys.pathはただのリストなので、append()メソッドなどで新たなパスを追加できる。
sys.pathにパスを追加したあとでimportを行うと、追加したパスの中のモジュールがインポートできる。
例えばスクリプトファイルの一階層上のディレクトリを追加する場合は以下のように書ける。
import os
import sys
sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
詳細は以下の記事を参照。
sys.pathへの追加が有効なのはそのコードの中だけ。恒久的に特定のパスを追加したい場合は次に説明するPYTHONPATHか.pthファイルを使う。
環境変数PYTHONPATHでモジュール検索パスを追加
恒久的にモジュール探索パスを追加する場合は、環境変数PYTHONPATHを使う。
自作のライブラリを標準ライブラリやpipでインストールしたサードパーティライブラリのように使いまわしたい場合は、自作ライブラリをまとめて格納するディレクトリを作って、そのディレクトリのパスを環境変数PYTHONPATHに設定する。
Macを含むUnix系OSの場合は、例えば~/.bashrcなどに以下のように追記する。複数パスを指定する場合コロン:で区切る。
export PYTHONPATH="/path/to/add:$PYTHONPATH"
Windowsの場合も通常の環境変数と同様に「PC(マイコンピュータ)を右クリック→「システム」→「システムのプロパティ」→「環境変数」からPYTHONPATHを新たに追加して設定すればOK。Windowsの場合は複数パスを指定する場合セミコロン;で区切る。
自作のライブラリをPYTHONPATHに追加したディレクトリに入れておけばsys.pathを処理することなくいつでもインポートして使えるようになるので便利。
上の例の'/Users/mbp/Documents/lib'というディレクトリはPYTHONPATHに追加したもの。
パス設定ファイル(.pth)でモジュール検索パスを追加
site-packagesディレクトリの中にパス設定ファイル(.pth)を置いておくと、その中身のパスもモジュール探索パスとして追加される。
パス設定ファイル(.pth)には1行に1つのパスを記述する。相対パスでも絶対パスでもOK。#でコメントを書くことも可能。拡張子がpthであればファイル名は何でもよい。