python のインタプリンタ自体の状態や、インタプリンタが動作しているシステムの状態を扱うモジュールです。
sys.meta_path
パッケージ/モジュールのインポートをカスタマイズするための変数 sys.meta_path はリストでありfinder クラスを登録する。
sys.meta_path は、finder クラスを登録したリストである。
finder クラスには find_module() メソッドを定義する。
finder クラスの find_module() メソッドは、インポートするモジュールを探すために呼び出される。
find_module() メソッドは、パッケージ/モジュールを探してモジュールが見つからなかった場合は None を、見つかった場合はローダーを生成して loader を返す。
ローダーのload_moduleメソッドで,モジュールを生成する。
インポートするモジュールがパッケージに含まれる場合、親パッケージの __path__ 属性を第 2 引数として渡す。
sys.meta_path は、デフォルトの暗黙の finder や、sys.path よりも先に検索される。
属性及び変数
__path__属性
パッケージを検索するディレクトリパスのリスト(パッケージ専用)。
パッケージは特別な属性として __path__ をサポートしています。
この属性は、パッケージの __init__.py 中のコードが実行されるよりも前に、__init__.py の収められているディレクトリ名の入ったリストになるよう初期化されます。
この変数は変更することができます。変更を加えると、以降そのパッケージに入っているモジュールやサブパッケージの検索に影響します。
__name__、 __file__
__loader__、 __package__
後日記述
sys.path
モジュールの検索パスを示す文字列のリスト。
次のようにすることで現在のPythonのモジュール検索パスを確認することができます。
import sys
sys.path
#---表示-------
['', 'C:\\Python33\\lib\\site-packages\\distribute-0.6.49-py3.3.egg', 'C:\\Pytho
n33', 'C:\\windows\\system32\\python33.zip', 'C:\\Python33\\DLLs', 'C:\\Python33
\\lib', 'C:\\Python33\\lib\\site-packages', '', 'C:\\Python33\\lib\\site-package
s\\distribute-0.6.49-py3.3.egg', 'C:\\Python33', 'C:\\windows\\system32\\python3
3.zip', 'C:\\Python33\\DLLs', 'C:\\Python33\\lib', 'C:\\Python33\\lib\\site-pack
ages']
このパスの順番でPythonモジュールが検索される。
この最初の空白行「”」はカレントパスを一番最初に検索するということ。
OSの環境変数にPYTHONPATHを追加していると、「”」とsys.pathの間に検索パスが追加されます。
また、一時的にパスを追加するのであれば
import sys
sys.path.append("c:\\temp")
これでsys.pathの最後にtempフォルダが追加され、tempの下に置いたPythonライブラリもインポートできるようになります。
【path優先順位】
- カレントパス
- PYTHONPATH
- sys.path
- sys.path.appendで追加したパス
sys.modules
sys.modules は import 済みモジュール名をキー、モジュールオブジェクトを値とした辞書です。
この辞書を確認することで import 済みのモジュールを確認できます。
>>> import sys
>>> sys.modules
{'copy_reg': <module 'copy_reg' from 'C:\python26\lib\copy_reg.pyc'>, 'sre_compi
le': <module 'sre_compile' from 'C:\python26\lib\sre_compile.pyc'>, 'encodings.c
p932': <module 'encodings.cp932' from 'C:\python26\lib\encodings\cp932.pyc'>,
...........
}
#---キー取得・表示-----
print '\n'.join(sys.modules.keys()) #---copy_reg sre_compi.....を表示
le
#---値取得-----
sys.modules["copy_reg"] #---<module 'copy_reg' from 'C:\python26\lib\copy_reg.pyc'>を表示
finder
モジュールの loader を探すオブジェクト(クラス)。 find_module() という名前のメソッドを実装していなければならない。
find_module() メソッド
インポートされた検索パスを検索して、パッケージ又はモジュールを探します。
find_module(self, fullname, path=None)
fullname・・・インポートするドットで区切られたフルパッケージ・モジュール名が渡される。
path・・・sys.meta_path に登録された finder クラスが呼び出された時にのみ値が渡される。
loader
モジュールをロードするオブジェクト。
load_module() という名前のメソッドを定義していなければならない。
ローダーは一般的に finder から返されます。
load_module(self, fullname)
fullname・・・インポートするドットで区切られたフルパッケージ・モジュール名が渡される。
load_module の決まり事
- 引数 fullname が sys.modules に既に登録されていた場合、登録済みのモジュールを返さなければならない。
- モジュールを生成する前に、sys.modules に登録を済ませなければならない。
- モジュールの生成に失敗した場合には、sys.modules に登録した登録した可能性のあるものを取り除かなければならない。
- パッケージ/モジュールの __file__ に何かしらの文字列を設定しなければならない。
- パッケージ/モジュールの __name__ に値を設定しなければならない。
- 生成されるのがパッケージである場合、パッケージ/モジュールの __path__ に値を設定しなければならない。
- パッケージ/モジュールの __loader__ にローダーを設定しなければならない。
- パッケージ/モジュールの __packge__ にパッケージ名を設定しなければならない。
【sys.meta_path は sys.path_hooks と同様にインポートフックですが、sys.path_hooks に登録するのとはいくつか違いがある。】
- sys.path を使ったインポートが処理される前に呼ばれる。つまり sys.path に関係なく使える。
- サブモジュール/サブパッケージを find_module する際に第2引数が渡される。
第2引数には親パッケージの __path__ が渡される。
sys.path_hooks
パッケージ/モジュールのインポートをカスタマイズするための変数 sys.path_hooksはリストでファインダクラスを登録する。
path を引数にとって、その path に対する finder の作成を試みる呼び出し可能オブジェクトのリスト。
finder の作成に成功した場合、その呼び出し可能オブジェクトは finder を返す。
失敗した場合は、ImportError を送出する。
【ImportError】
import 文でモジュール定義を見つけられなかった場合や、from … import 文で指定した名前をインポートすることができなかった場合に送出されます。
sys.meta_pathとsys.path_hooksの違い
sys.path_hooksはsys.pathからモジュールを探す時のフックであるのに対して、sys.meta_pathはsys.pathとは独立に動作するということです。
つまりsys.meta_pathはsys.pathに登録されていないパスからモジュールをインポートする、または動的にモジュールを生成してロードさせることもできます。
sys.path_importer_cache
finder オブジェクトのキャッシュとなる辞書。
キーは sys.path_hooks に渡される path。
値は見つかった finder オブジェクト。
path が有効なファイルシステムパスであり、かつ finder オブジェクトがsys.path_hooks から見つからない場合、暗黙のデフォルト finder を利用するという意味で None が格納されます。
path が既存のパスではない場合、 imp.NullImporter が格納されます。
sys.exit
Pythonのsysモジュールに含まれるsys.exit()という関数は呼び出すとプログラムを終了し、引数をプロセスの戻り値にする。
sys.exit([arg])
argは、終了コード。指定しない場合は、0となる。
通常は、整数をいれるが、整数以外も入れることが可能。
一般的には、0が正常終了、0以外が異常終了ですが、システムによって、多少異なる。
例(シェルで確認)
import sys
def main():
print('exit test before')
sys.exit(end())
print('exit test after')
def end():
print('終了します。')
if __name__ == '__main__':
main()
▼結果
exit test before
終了します。を表示してpythonを終了。
sys.exit()で、即終了するので、その後の処理は行なわない。
sys.stdin
標準入力に対応するファイルオブジェクト。
標準入力から読むには、sys をimport しておき、sys.stdin を用います。
下記は、1行ずつ、標準入力から読んで標準出力に書き出す。
import sys
for line in sys.stdin:
print line,
▼結果
シェルに「123」と入力し、enter。
「123」と表示される。
sys.stdout
標準出力に対応するファイルオブジェクト。
print 文に変わる出力。
write と writelines のメソッドがある。
import sys
sys.stdout.write('Hello') #---Hello5と表示---
※)sys.stdout.writeは、書き込まれた文字数も返す。
print 文だと改行の代わりに半角スペースがひとつ入ってしまうのですが、
改行も半角スペースも入れたくない場合には、sys.stdout.write()を使う。
print文は内部的にはこのsys.stdoutのラッパ関数だそうだ。
sys.stdoutのwrite()関数を呼び出すと、そこに与えた文字列をなんでも表示する。
実際に、これがprint関数の行っていることだ。
print関数は表示する文字列の末尾に改行を追加して、sys.stdout.writeを呼び出す。
sys.stdout などに新たなファイルライクオブジェクトを代入することで
print 文などの 出力先を変更することができる。
import sys
foo = open('foo.txt', 'w');
sys.stdout = foo; ①
sys.stdout.write('adcb'); ②
print('efg') ※⑤
sys.stdout = sys.__stdout__; ③
f.close(); ④
- ①:sys.stdout ファイルオブジェクトに foo ファイルオブジェクトを代入。
- ②:write メソッドでファイルに「’adcb’」を書き込む。
「foo.txt」に abcd が書き込まれる。 - ③:sys.stdout には foo ファイルオブジェクトが入っているので元の値に戻す。
- ④:ファイルを閉じる。これを書かないと結果が反映されない。
- ※⑤:print 文の 出力先を変更。
foo.txt に efg が書き込まれる。結果 foo.txt の内容は、abcdefg となる。
sys.argv
sysモジュールの、sys.argv により、コマンドラインに入力したパラメータ(引数)を受け取ることができます。
Python ではコマンドライン引数は sys モジュールの argv 属性に文字列を要素とするリストとして格納されます。
import sys
if __name__ == "__main__":
print(sys.argv)
print("第1引数:" + sys.argv[1])
print("第2引数:" + sys.argv[2])
print("第3引数:" + sys.argv[3])
▼下記をコマンドで実行(aa,bb,cc の3つの引数を渡す)
python C:\Python33\test.py aa bb cc
▼結果
[‘C:\Python33\test.py’, ‘aa’, ‘bb’, ‘cc’]
第1引数:aa
第2引数:bb
第3引数:cc
※)sys.argv[0]には実行ファイル名が入る。