Pythonがモジュールを検索する流れをざっくりと把握してから、別ディレクトリにあるモジュールのパスを通す方法を見ていきます。
パスを通す場所というのは3つあるのですが、その場所というのは、
- sys.path
- .pthファイル
- 環境変数のPYTHONPATH
です。
このいずれかにパスを記述します。
以下で詳しくやっていこうと思います。
使用した環境
Windows10
Docker Python 3.9.0[Debian]
Python 3.10.5
モジュールの検索
import文があったときに、Pythonはビルトインモジュール(一部の標準ライブラリ。sysなど)を検索し、見つからなかったときにsys.path(リスト)に入っているパスから順に探していきます。
6.1.2. モジュール検索パス
いちどsysをインポートし、sys.pathを確認してみましょう。
コンソール画面
$ docker run -it --rm python Python 3.9.0 Type "help", "copyright", "credits" or "license" for more information. >>> import sys >>> sys.path ['', '/usr/local/lib/python39.zip', '/usr/local/lib/python3.9', '/usr/local/lib/python3.9/lib-dynload', '/usr/local/lib/python3.9/site-packages']
私の環境では上のようになりました。
環境によってディレクトリの構成が異なるかもしれませんが、
「'/usr/local/lib/python3.9'」には、ramdomやdatetimeなどの標準ライブラリが入っています。
「'/usr/local/lib/python3.9/site-packages'」には、任意でインストールしたモジュールがあります。
リスト先頭の「''」はカレントディレクトリです。
もしモジュールから実行した場合、先頭にはそのモジュールの入っているディレクトリのパスが入ります。
ちょっとやってみましょう。
/code/test.py
import sys
print(sys.path)
コンソール
$ python /code/test.py
['/code', '/usr/local/lib/python39.zip', '/usr/local/lib/python3.9', '/usr/local/lib/python3.9/lib-dynload', '/usr/local/lib/python3.9/site-packages']
モジュールの中でsys.pathを表示させると、上記リストの一番目が「'/code'」になっています。
カレントディレクトリ内にモジュールがあるときや、pipでインストールしたものなどはパスが通っていますが、それ以外の場合は、パスを追加する必要があります。
カレントディレクトリ内にあるモジュール・パッケージの呼び出し方↓
パスを通すには
Pythonにパスを通すには、これから挙げる3つのどれかにパスを書きます。
- sys.path
- .pthファイル
- 環境変数のPYTHONPATH
これからひとつずつやっていきますが、共通事項として、モジュールのファイル名が「mymodule.py」、モジュールを収めているディレクトリのパスが「/mypackage」とし、カレントディレクトリのパスが「/code」として作業を進めます。
ファイル構成のイメージ
mymodule.py
print('from mymodule')
インポートに成功すると、「from mymodule」と表示させるシンプルなモジュールです。
そもそもパスについてよく分からないという人は先に↓を参考にしてください。
sys.path
sys.pathはリストなので、メソッドのappendを使ってパスを追加することができます。
import sys
sys.path.append('ディレクトリのパス')
さっそくやってみようと思います。
コンソール画面
Python 3.9.0 Type "help", "copyright", "credits" or "license" for more information. >>> import sys >>> sys.path.append('/mypackage') >>> sys.path ['', '/usr/local/lib/python39.zip', '/usr/local/lib/python3.9', '/usr/local/lib/python3.9/lib-dynload', '/usr/local/lib/python3.9/site-packages', '/mypackage']
リストの末尾に'/mypackage'が追加されていますね。
モジュールをインポートします。
>>> import mymodule from mymodule
「/mypackage」へのパスが通っているので、中に入っているmymoduleをインポートすることに成功しました。
ただしsys.pathへの追加は一時的なものです。
Pythonを一度終了し、再びmymoduleをインポートしようとするとエラーになります。
Python 3.9.0 Type "help", "copyright", "credits" or "license" for more information. >>> import mymodule Traceback (most recent call last): File "<stdin>", line 1, in <module> ModuleNotFoundError: No module named 'mymodule' >>> import sys >>> sys.path ['', '/usr/local/lib/python39.zip', '/usr/local/lib/python3.9', '/usr/local/lib/python3.9/lib-dynload', '/usr/local/lib/python3.9/site-packages']
sys.pathに「'/mypackage'」はありません。
実行モジュール内で「sys.path.append」することで別ディレクトリのモジュールを使えるようにはなります。
実行用モジュールを新規作成
/code/main.py
import sys
sys.path.append('/mypackage')
import mymodule
コンソール画面
python main.py from mymodule
mainのコードでは、sysを呼んでからリストに追加し、次の行でようやく呼び出したいモジュールをインポートしています。
これはPEP8 - Style Guide for Python[Imports]に反しているので、気になる方はいるでしょうし、モジュールを公開する場合に推奨する方法ではありません。
.pthファイル
拡張子が「.pth」のファイルを作成します。ファイルを保存する場所は、sitepackagesのなかです。
まずsitepackagesの場所を確認しましょう。
sys.pathで確認してもいいですが、今回はPythonを起動して以下を実行します。
import site
site.getsitepackages()
Python 3.9.0 >>> import site >>> site.getsitepackages() ['/usr/local/lib/python3.9/site-packages']
私の環境では'/usr/local/lib/python3.9/site-packages'と出ました。
そのディレクトに移動します。
ファイルを作成し、追加したいパスを書きます。
複数のパスを追加したい場合、改行して一行ずつ記入してください。
拡張子を.pthにします。
test.pth
※ファイル名は自身がわかりやすければ何でも構いません
/mypackage
確認のため実行します。
Python 3.9.0 >>> import mymodule from mymodule
printがちゃんと実行されていますね。
環境変数・PYTHONPATH
環境変数名「PYTHONPATH」にパスを入れます。
Unix系とWindowsで分けて説明。
Unix系
コンソールから、
export PYTHONPATH=ディレクトリのパス で行います。
複数のパスを追加したい場合、パスとパスの間を:(コロン)でつなぎます。
$ export PYTHONPATH=/mypackage $ python Python 3.9.0 >>> import mymodule from mymodule >>> import sys >>> sys.path ['', '/mypackage', '/usr/local/lib/python39.zip', '/usr/local/lib/python3.9', '/usr/local/lib/python3.9/lib-dynload', '/usr/local/lib/python3.9/site-packages']
PYTHONPATHで書いたパスは、sys.pathのリストの2番目に追加されていますね。
ただしこちらの方法も一時的なものなので、常時有効にするには、.bashrcに書いておきましょう。
また一度作成したPYTHONPATHにパスを追記したいときには以下のように書きます。
export PYTHONPATH=$PYTHONPATH:追加したいディレクトリのパス
Windows
Windowsでは「コマンドプロンプト」と「PowerShell」でコマンドが異なります。
自身の使っている方を選んでください。
コマンドプロンプト | PowerShell |
---|---|
set PYTHONPATH=フォルダのパス | $env:PYTHONPATH="フォルダのパス" |
確認するにあたってフォルダの構成が変わります。
「C:\Users\fujino\Documents\」のなかに「code」と「mypackage」フォルダがあり、「mypackage」に「mymodule.py」があるものとします。
作業フォルダは「code」です。
コマンドプロンプトでパスを通します。
>set PYTHONPATH=C:\Users\fujino\Documents\mypackage >py Python 3.10.5 (tags/v3.10.5:f377153, Jun 6 2022, 16:14:13) [MSC v.1929 64 bit (AMD64)] on win32 Type "help", "copyright", "credits" or "license" for more information. >>> import mymodule from mymodule >>> import sys >>> sys.path ['', 'C:\\Users\\fujino\\Documents\\mypackage', # 以下略]
PowerShellの場合です。
> $env:PYTHONPATH="C:\Users\fujino\Documents\mypackage" > py Python 3.10.5 (tags/v3.10.5:f377153, Jun 6 2022, 16:14:13) [MSC v.1929 64 bit (AMD64)] on win32 Type "help", "copyright", "credits" or "license" for more information. >>> import mymodule from mymodule
ここで設定した環境変数も一時的なものです。
まとめ
モジュール検索の流れと、パスを追加する3つの場所について見てきました。
モジュール検索はビルトインモジュール、sys.pathのリストの中から順に行われる
sys.pathにappendメソッドでパスを追加
sitepackagesのなかに拡張子.pthのファイルを作成してパスを記入
環境変数PYTHONPATHを定義して追加する