メモ代わり。てきとーに。 いや、ですからてきとーですって。 2年前ぐらいにPythonあたりでメールくれた方、ごめんなさい。メール紛失してしまい無視した形になってしまいました。。。

2008年2月15日金曜日

[Python][お勉強] Python入門(35) - インポートの処理

ひきつづき「インポートの処理」を見ていく。

インポートの処理は大きく3つのプロセスに分けることができる。

  1. インポート対象のモジュールファイルを探す
  2. ファイルのコンパイル
  3. モジュールを実行し、オブジェクトを生成
上記3つのプロセスをひとつづつ見ていく。



1. インポート対象のモジュールファイルを探す

モジュールファイルを探すのにはモジュールサーチパスなるものが利用される。
基本的にはモジュールサーチパスは自動で設定される。
モジュールサーチパスは4つの要素を持つ。その要素を以下に記す。
  1. トップレベルファイルのホームディレクトリ
  2. 環境変数PYTHONPATHで指定されたディレクトリ
  3. 標準ライブラリモジュールのディレクトリ
  4. .pthファイルの内容
モジュールサーチパスを変更するときは、通常、環境変数PYTHONPATHか.pthを変更する。
1が最初に検索され、なければ2を。最後に4を検索される。


トップレベルファイルのホームディレクトリ
ホームディレクトリとは、通常トップレベルファイルが置かれているディレクトリを指す。
モジュールインポート時には最初に検索される場所。

環境変数PYTHONPATH
環境に依存したディレクトリパスを記述しておく環境変数。
複数の値を設定でき、複数指定された場合には左端から順に検索される。
設定された値がトップレベルファイルのホームディレクトリの次に検索される場所になる。

標準ライブラリモジュールのディレクトリ
標準ライブラリがインストールされているディレクトリ。
環境変数PYTHONPATHの値の次に検索される場所。

.pthファイルの内容
.pthファイルとは.pthという拡張子の付いたテキストファイルのこと。
一行に1パスづつ複数行指定できる。このファイルを「適切な場所」に設置すると
.pthファイルの内容の最初の行から順にそれぞれの行の値の場所を検索してくれる。
「適切な場所」がどこかは今のところ不明。


上記4つのサーチパスをプログラム上から触ることもできる。
sysモジュールのpath属性の値を調べればサーチパスのリストを取得できる。

>>> import sys
>>> sys.path
['', '/usr/lib/python24.zip', '/usr/lib/python2.4', '/usr/lib/python2.4/plat-linux2',
'/usr/lib/python2.4/lib-tk', '/usr/lib/python2.4/lib-dynload',
'/usr/local/lib/python2.4/site-packages', '/usr/lib/python2.4/site-packages',
'/var/lib/python-support/python2.4']
>>>


と、こんな感じ。

また、サーチパスをカスタマイズするプログラムも、sys.pathを使用すれば作成できるとのこと。


インポートできるファイルの種類
インポートできるファイルの種類は、以下のとおり。
  • ソースファイル(.py)
  • バイトコードファイル(.pyc)
  • パッケージインポートのためのディレクトリ
  • Cエクステンションモジュール(.so)
  • フローズンバイナリに対応するメモリイメージ
  • Jythonの場合のJavaクラス
  • zipファイルコンポーネント(zipimportステートメントを利用)
同じディレクトリに同一名で同じ違う種類のファイルが存在する場合は、
優先順位にルールがあるものの、いつ変わるかわからないからなんとも言えないらしい。




2.見つかったファイルのコンパイル
.pyファイルが見つかると次は.pycファイルを生成すべくコンパイルをする。
ただしコンパイルされない場合もある。
  • .pyファイルよりも.pycファイルの方が新しい場合
  • .pycファイルしか対象ディレクトリになかった場合
が、コンパイルされない場合とのこと。
注意点としては、.pycファイルはインポートのタイミングで作成されるものである、という点。




3.モジュールの実行
コンパイルプロセスが終わると、次はモジュール中のコードが実行され、そのモジュールに対応するモジュールオブジェクトが生成される。このときモジュール中のコードが最初の行から1つづつ実行される。
仮にprintステートメントが書かれていればインポート時に出力されたりする。
defステートメントがあればdefステートメントが実行され、関数オブジェクトが生成され、関数名に代入される。

インポート処理によってモジュールが実行されるということは、コードの内容によってはインポート時点でなんらかの処理結果が得られる場合もあるということを意味する。



これらの3つのステップは既にインポート済みの場合には実行されない。
既にインポート済みの場合にはメモリ中にロードされているモジュールが再利用される。
既にインポート済みかどうかはsys.modulesを見ればわかるとのこと。


>>> import sys
>>> sys.modules.keys()
['copy_reg', '__main__', 'site', '__builtin__', 'encodings',
'posixpath', 'encodings.codecs', 'os.path', '_codecs',
'encodings.exceptions', 'stat', 'zipimport', 'warnings',
'encodings.types', 'UserDict', 'encodings.utf_8', 'sys',
'codecs', 'readline', 'types', 'signal', 'linecache', 'posix',
'encodings.aliases', 'exceptions', 'os']
>>>


Debian-Etchでデフォルト状態のPythonで起動しただけのトップレベルの場合には上記のようになった。



ふーん。


おしまい。
.

0 コメント: