PythonのImportメカニズム
4566 ワード
Pythonプログラムでは、import文が現在のプログラムで使用するための新しいモジュールをインポートします.importの基本文法は
sys.path
もちろん、
PYTHONPATH
実行中に
複数の検索パスを指定する場合は、
モジュールの再ロード
前述したように、Pythonがモジュールのロードを完了すると、
環境変数
Python環境で
Reference Python Documentation: The Import System How to set your Python path How does python find packages
import module_name
です.import文を実行すると、Python解釈器はまずmodule_を検索します.nameが指すソースファイルは、メモリにロードされ、新しくインポートしたモジュールを変数にバインドします.これにより、後続の操作で、このバインドされた変数から新しくインポートされたモジュールにアクセスできます.sys.path
import module_name
の場合、Pythonはsys.path
で指定されたフォルダリストの順に検索します.sys.path
は、オペレーティングシステムやコンパイルパラメータに応じて、デフォルトでは異なるフォルダリストが格納されるリストタイプです.また、プログラム実行中に、動的にsys.path
にコンテンツを追加または削除し、必要なロードモジュールのニーズを実現することもできる.現在のArch Linux(kernel 4.19.21)マシンで、Python 3.7のsys.path
を以下のように表示します.$ python
Python 3.7.1 (default, Oct 22 2018, 10:41:28)
[GCC 8.2.1 20180831] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> sys.path
['', '/usr/lib/python37.zip', '/usr/lib/python3.7', '/usr/lib/python3.7/lib-dynload', '/home/hong/.local/lib/python3.7/site-packages', '/usr/lib/python3.7/site-packages']
sys.path
のデフォルトの最初のフォルダアドレスは空で、現在の作業ディレクトリであるos.getcwd()
を指す.そのため、モジュールを検索する際、Pythonはまず現在の作業ディレクトリを検索します.正常にロードされたモジュールは、sys.modules
辞書に格納されます.1つのモジュールがロードに成功し、sys.modules
に存在する場合、次にモジュールに対してロード操作を実行すると、検索操作は実行されず、sys.modules
から直接戻る.$ mkdir /tmp/demo
$ touch /tmp/demo/__init__.py # /tmp , demo
$ python
>>> import os, sys
>>> import demo # /tmp sys.path ,
Traceback (most recent call last):
File "", line 1, in
ModuleNotFoundError: No module named 'demo'
>>> 'demo' in sys.modules
False
>>> os.chdir('/tmp/') # /tmp,
>>> import demo
>>> demo
>>> demo.__path__
['/tmp/demo']
>>> 'demo' in sys.modules
True
もちろん、
sys.path
フォルダリストに'/tmp'フォルダを追加することにより、上記demo
モジュールをロードしてもよい.$ python
>>> import sys
>>> sys.path.append('/tmp')
>>> import demo
>>> demo
['/tmp/demo']
PYTHONPATH
実行中に
sys.path
を変更するだけでなく、環境変数PYHTONPATH
を使用してモジュール検索のパスを指定することもできます.Pythonは、PYTHONPATH
のコンテンツをsys.path
の現在の作業ディレクトリ''
と他のデフォルトの検索パスの間に配置します.$ export PYTHONPATH='/tmp'
$ python
>>> import sys
>>> sys.path
['', '/tmp', '/usr/lib/python37.zip', '/usr/lib/python3.7', '/usr/lib/python3.7/lib-dynload', '/home/hong/.local/lib/python3.7/site-packages', '/usr/lib/python3.7/site-packages']
複数の検索パスを指定する場合は、
PYTHONPATH
に配置します.異なる検索パスの間には区切り記号が必要ですが、オペレーティングシステムの習慣によって、異なるシステムで区切り記号の違いが発生します.$ export PYTHONPATH='/tmp:/tmp/lib2'
$ python
>>> import sys
>>> sys.path
['', '/tmp', '/tmp/lib2', '/usr/lib/python37.zip', '/usr/lib/python3.7', '/usr/lib/python3.7/lib-dynload', '/home/hong/.local/lib/python3.7/site-packages', '/usr/lib/python3.7/site-packages']
モジュールの再ロード
前述したように、Pythonがモジュールのロードを完了すると、
sys.modules
に新しいモジュールが配置されます.モジュールが再ロードされると、異なる検索操作が実行され、sys.modules
から直接返される.しかし、モジュールのソースコードを変更した場合、モジュールを完全に再ロードする必要がある場合があります.この場合、sys.modules
に保存されている元モジュールを削除してから、import
操作を実行すればよい.環境変数
PYTHONPATH
により、上記demo
モジュールがロードされる.$ export PYTHONPATH='/tmp'
$ python
>>> import demo
>>> demo.message
Traceback (most recent call last):
File "", line 1, in
AttributeError: module 'demo' has no attribute 'message'
demo
モジュールにはmessage
変数が存在せず、アクセスエラーが発生しました.demo
モジュールを変更し、message
変数を追加します.$ echo "message='this is a message.'" > /tmp/demo/__init__.py
Python環境で
demo
モジュールを再ロードします.>>> import sys
>>> sys.modules.pop('demo')
>>> import demo
>>> demo.message
'this is a message'
Reference