6. モジュール

Python インタープリタを終了させ、そして再び起動したとき、 いままでしてきた定義 (関数と変数) は失われてしまう。 だから、もし何かもっと長いプログラムを書きたいならば、 直接入力するのではなく、 テキストエディタを使ってインタープリタへの入力を用意し、 そして入力としてそのファイルを使ってインタープリタを走らせるのが良い。 これはスクリプト (script) の作成として知られている。 プログラムが長くなるにつれ、メンテナンスをしやすくするため、 プログラムを複数のファイルに分割したくなるかもしれない。 あるいは、いくつかのプログラムで書いてきた便利な関数を、その定義をいちいち 各プログラムのなかに書き写すことなく使いたくなるかもしれない。

これをサポートするため、Python には、いくつかの定義を一つのファイルに置き、 そしてそれらをスクリプトや対話的に起動したインタープリタの中で使う方法がある。 そのようなファイルをモジュール (module) と呼ぶ。 モジュールからの定義は、ほかのモジュールの中へ、 またはメインモジュール (トップレベルで実行されるスクリプトの中 や電卓モードの中で、君がアクセスできる変数の集まり) の中へ 輸入 (import) することができる。

モジュールは Python の定義と文からなるファイルだ。 そのファイル名はモジュール名に接尾辞 .py を付けたものだ。 モジュール内では、そのモジュールの (文字列としての) 名前を グローバル変数 __name__ の値として得ることができる。 例として、好きなテキストエディタを使って、現在のディレクトリに 以下の内容で fibo.py という名前のファイルを作成しよう。

# フィボナッチ数列モジュール

def fib(n):    # nまで加算されるフィボナッチ級数を印字
    a, b = 0, 1
    while b < n:
        print b,
        a, b = b, a+b

def fib2(n): # nまで加算されるフィボナッチ級数を返す
    result = []
    a, b = 0, 1
    while b < n:
        result.append(b)
        a, b = b, a+b
    return result

次に Python インタープリタに入り、このモジュールを以下のコマンドで輸入しよう。

>>> import fibo

これは fibo の中で定義されている各関数の名前をじかに現在の記号表に 入れているわけではない。 モジュール名 fibo だけを現在の記号表に入れている。 関数へはモジュール名を使ってアクセスできる。

>>> fibo.fib(1000)
1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987
>>> fibo.fib2(100)
[1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]
>>> fibo.__name__
'fibo'

もしも関数をたびたび使うつもりならば、それをローカル名に代入してもよい。

>>> fib = fibo.fib
>>> fib(500)
1 1 2 3 5 8 13 21 34 55 89 144 233 377

 
6.1 もっとモジュールについて

モジュールには関数定義だけでなく実行文を含めてもよい。 これらの文の目的はモジュールの初期化だ。 それらはモジュールがどこであれ最初に輸入されたときだけ 実行される6.1

モジュールは各自、プライベートな記号表を持っており、 モジュールの中で定義されたすべての関数はそれをグローバル記号表として使用する。 したがって、モジュールの著者は、 利用者のグローバル変数と偶然かちあうかもしれないという心配をすることなく、 モジュールの中でグローバル変数を使うことができる。 他方、もしも自分が何をしているのかをわきまえているならば、 モジュールの関数への参照と同じ記法 modname.itemname を使って、 モジュールのグローバル変数に触ってもよい。

モジュールはほかのモジュールを輸入できる。 慣習であって必須なわけではないが、 すべての import 文をモジュールの先頭に置くべきだ (これに 関してはスクリプトでも同様だ)。 輸入されるモジュールの名前が、 輸入をするモジュールのグローバル記号表に置かれる。

import 文には、モジュールからの名前を、 輸入をするモジュールの記号表の中へじかに輸入するという変種がある。 たとえば、

>>> from fibo import fib, fib2
>>> fib(500)
1 1 2 3 5 8 13 21 34 55 89 144 233 377

これは輸出元のモジュールの名前を、ローカルな記号表に導入することは しない (だから、この例では fibo は定義されない)。

モジュールが定義する名前をすべて輸入するという変種さえある。

>>> from fibo import *
>>> fib(500)
1 1 2 3 5 8 13 21 34 55 89 144 233 377

これは、下線 (_) で始まる名前を除くすべての名前を輸入する。

 
6.1.1 モジュール検索パス

 spam という名前のモジュールを輸入するとき、 インタープリタは spam.py という名前のファイルを、 まず現在のディレクトリから、そして次に環境変数 PYTHONPATH で 指定されたディレクトリの並びから検索する。 この環境変数はシェル変数 PATH と同じ構文、 つまりディレクトリ名の並びだ。 PYTHONPATH がセットされていないとき、 またはファイルがそこから見つからないとき、 検索はインストールの仕方に依存するデフォルトのパスで続行される。 Unixでは、これは普通 .:/usr/locall/lib/python だ。

実際には、モジュールは、変数 sys.path が与えるディレクトリの 並びから検索される。 この変数は入力スクリプトの所在するディレクトリ (または現在のディレクトリ)、 PYTHONPATH、およびインストールの仕方に依存するデフォルト値で 初期化される。 これにより、自分が何をしているのかをわきまえている Python プログラムは、 モジュール検索パスを修正または置換することができる。 実行しているスクリプトを含んでいるディレクトリーが探索パス上にあるので、 スクリプトが標準モジュール、あるいは Python がモジュールを輸入する時ロー ドするモジュールとしてのスクリプト、と同じ名前を持っていないことが重要 だ。 同じ名前である場合、通常エラーになる。 さらなる情報は 6.2,``標準モジュール.'' の節を参照されたい。

6.1.2 ``コンパイル'' された Python ファイル

沢山の標準モジュールを使う短いプログラムにとって重要な起動時間の高速化として、 もしも spam.py が見つかったディレクトリに spam.pyc という名前の ファイルがあったならば、 それはモジュール spam の ``バイトコンパイル'' 済みのバージョン であると仮定される。 spam.pyc を造るために使われたバージョンの spam.py の ファイル修正時刻が spam.pyc に記録されていて、 もしもこれが不一致ならば spam.pyc ファイルは無視される。

通常、spam.pyc ファイルを造るために何もする必要はない。 spam.py が無事コンパイルされたときはいつでも、 コンパイルされたバージョンを spam.pyc へ書くことが試みられる。 この試みが失敗してもエラーではない。なんらかの理由でファイルが完全には 書けなかったとき、結果として残された spam.pyc ファイルはその後、 無効であると認識され、したがって無視されることになる。 spam.pyc ファイルの内容はプラットフォームに依存しないから、 Python モジュールのディレクトリを、 別々のアーキテクチャのマシン間で共有することができる。

エキスパートへの助言:

 
6.2 標準モジュール

Python には標準モジュールのライブラリが付属していて、 別のドキュメント Python Library Reference (これ 以降 ``Library Reference'') で記述されている。 モジュールにはインタープリタの中に組み込まれているものもある。 それらは言語の核の部分ではないが、効率のために、 またはシステムコールなどのオペレーティングシステムの基本要素への アクセスを提供するために組み込まれている。 このようなモジュールのセットは構成オプションであり、また 実行プラットフォームに依存する。 たとえば amoeba モジュールは、なんであれ Amoeba基本要素を サポートしているシステムでだけ用意される。 いくらかの注目に値する1個のモジュールがある。 それは sys だ。 これはどの Python インタープリタにも組み込まれている。 変数 sys.ps1sys.ps2 は、 一次と二次のプロンプトとして使われる文字列を定義する。

>>> import sys
>>> sys.ps1
'>>> '
>>> sys.ps2
'... '
>>> sys.ps1 = 'C> '
C> print 'Yuck!'
Yuck!
C>

これら二つの変数はインタープリタが対話モードにあるときだけ定義される。

変数 sys.path は文字列のリストで、 モジュールを探すためのインタープリタの検索パスを決定する。 これは環境変数 PYTHONPATH から、またはそれがセットされて いなければ組込みのデフォルト値から、取られたデフォルトのパスに初期化される。 君はこれを標準的なリスト演算を使って改変できる。

>>> import sys
>>> sys.path.append('/ufs/guido/lib/python')

 
6.3 dir() 関数

組込み関数 dir() は、 あるモジュールがどの名前を定義しているかを調べるために使われる。 これは文字列のソートされたリストを返す。

>>> import fibo, sys
>>> dir(fibo)
['__name__', 'fib', 'fib2']
>>> dir(sys)
['__displayhook__', '__doc__', '__excepthook__', '__name__', '__stderr__',
 '__stdin__', '__stdout__', '_getframe', 'api_version', 'argv', 
 'builtin_module_names', 'byteorder', 'callstats', 'copyright',
 'displayhook', 'exc_clear', 'exc_info', 'exc_type', 'excepthook',
 'exec_prefix', 'executable', 'exit', 'getdefaultencoding', 'getdlopenflags',
 'getrecursionlimit', 'getrefcount', 'hexversion', 'maxint', 'maxunicode',
 'meta_path', 'modules', 'path', 'path_hooks', 'path_importer_cache',
 'platform', 'prefix', 'ps1', 'ps2', 'setcheckinterval', 'setdlopenflags',
 'setprofile', 'setrecursionlimit', 'settrace', 'stderr', 'stdin', 'stdout',
 'version', 'version_info', 'warnoptions']

引数がないとき、dir() は君が現在定義している名前をリストする。

>>> a = [1, 2, 3, 4, 5]
>>> import fibo, sys
>>> fib = fibo.fib
>>> dir()
['__name__', 'a', 'fib', 'fibo', 'sys']

これは変数やモジュールや関数など、すべての種類の名前を リストすることに注意するように。

dir() は組込みの関数や変数の名前はリストしない。 もしもそれらのリストが欲しいなら、 それらは標準モジュール __builtin__ で 定義されている。

>>> import __builtin__
>>> dir(__builtin__)
['ArithmeticError', 'AssertionError', 'AttributeError',
 'DeprecationWarning', 'EOFError', 'Ellipsis', 'EnvironmentError',
 'Exception', 'False', 'FloatingPointError', 'IOError', 'ImportError',
 'IndentationError', 'IndexError', 'KeyError', 'KeyboardInterrupt',
 'LookupError', 'MemoryError', 'NameError', 'None', 'NotImplemented',
 'NotImplementedError', 'OSError', 'OverflowError', 'OverflowWarning',
 'PendingDeprecationWarning', 'ReferenceError',
 'RuntimeError', 'RuntimeWarning', 'StandardError', 'StopIteration',
 'SyntaxError', 'SyntaxWarning', 'SystemError', 'SystemExit', 'TabError',
 'True', 'TypeError', 'UnboundLocalError', 'UnicodeError', 'UserWarning',
 'ValueError', 'Warning', 'ZeroDivisionError', '__debug__', '__doc__',
 '__import__', '__name__', 'abs', 'apply', 'bool', 'buffer',
 'callable', 'chr', 'classmethod', 'cmp', 'coerce', 'compile', 'complex',
 'copyright', 'credits', 'delattr', 'dict', 'dir', 'divmod',
 'enumerate', 'eval', 'execfile', 'exit', 'file', 'filter', 'float',
 'getattr', 'globals', 'hasattr', 'hash', 'help', 'hex', 'id',
 'input', 'int', 'intern', 'isinstance', 'issubclass', 'iter',
 'len', 'license', 'list', 'locals', 'long', 'map', 'max', 'min',
 'object', 'oct', 'open', 'ord', 'pow', 'property', 'quit',
 'range', 'raw_input', 'reduce', 'reload', 'repr', 'round',
 'setattr', 'slice', 'staticmethod', 'str', 'string', 'sum', 'super',
 'tuple', 'type', 'unichr', 'unicode', 'vars', 'xrange', 'zip']

 
6.4 パッケージ

パッケージ (package) は、Python のモジュール名前空間 を ``ドット付きモジュール名'' (dotted module names) を使って 構造化する手段だ。 たとえば、モジュール名 A.B は、 "A" というパッケージの "B" という下位モジュールを表す。 ちょうど、モジュールを利用すると、別々のモジュールの著者が互いの グローバル変数名について心配しなくても済むようになるのと同じように、 ドット付きモジュール名を利用すると、 NumPy や Python Imaging Library のような複数モジュールからなる パッケージの著者が互いのモジュール名について心配しなくても済むようになる。

サウンドファイルとサウンドデータの統一的な処理のための モジュール群 (``パッケージ'') を、設計しようとしていると仮定しよう。 サウンドファイルのフォーマットには多くの種類がある (普通 それらは .wav, .aiff, .au など接尾辞で認識される) から、 次第に増大するさまざまなファイルフォーマット間の変換用モジュール群を 作成し維持する必要があるかもしれない。 サウンドデータに施そうとする演算にも (ミキシング、エコーの追加、 イコライザ関数の適用、人工的なステレオ効果の作成など) 多くの種類があるだろう から、さらにこれらの演算を施す一連のモジュールを果てしなく書くことに なるだろう。 パッケージの構造は (階層的なファイルシステムで表現すると) こんな 感じになるだろう。

Sound/                          トップレベルのパッケージ
      __init__.py               サウンドパッケージを初期化する
      Formats/                  ファイルフォーマット変換用の下位パッケージ
              __init__.py
              wavread.py
              wavwrite.py
              aiffread.py
              aiffwrite.py
              auread.py
              auwrite.py
              ...
      Effects/                  サウンド効果用の下位パッケージ
              __init__.py
              echo.py
              surround.py
              reverse.py
              ...
      Filters/                  フィルタ用の下位パッケージ
              __init__.py
              equalizer.py
              vocoder.py
              karaoke.py
              ...

パッケージを輸入する時、 Python は パッケージのサブディレクトリを sys.path 上のディレクトリから捜す。

ファイル __init__.py は、Python にそのディレクトリを パッケージを収めているものとして取り扱わせるために必要だ。 これは "string" のようなよくある名前のディレクトリが、 モジュール検索パスの後のほうで出現する正当なモジュールを、 意図せず隠蔽してしまうことを防止する。 最も簡単には __init__.py はただの空ファイルでよいが、 そのファイルで、パッケージに対する初期化コードを実行したり、 後述する __all__ 変数をセットしてもよい。

パッケージの利用者は個々のモジュールをパッケージから輸入できる。たとえば、

import Sound.Effects.echo

これは下位モジュール Sound.Effects.echo をロードする。 それはフルネームで参照しなければならない。

Sound.Effects.echo.echofilter(input, output, delay=0.7, atten=4)

下位モジュールを輸入するもう一つの方法は、

from Sound.Effects import echo

これも下位モジュール echo をロードする。 そしてこれは echo をパッケージ接頭辞なしで利用可能にするから、 次のように使用できる。

echo.echofilter(input, output, delay=0.7, atten=4)

さらにもう一つのバリエーションは、欲しい関数や変数をじかに輸入する方法だ。

from Sound.Effects.echo import echofilter

やはり、これも下位モジュール echo をロードするが、 これはその関数 echofilter をじかに利用可能にする。

echofilter(input, output, delay=0.7, atten=4)

from package import item を使うとき、項目 item は、 パッケージ package の下位モジュール (または下位パッケージ) でもよいし、 package で定義される他の名前 (関数やクラスや変数などの名前) でも よいことに注意しよう。 import 文は、 itempackage で定義されているかどうかをまず調べ、 もしも定義されていなければ、モジュールだと仮定してロードを試みる。 もしそれを見つけることができなければ、 ImportError が発生する。

対照的に、import item.subitem.subsubitem のような構文を 使ったときは、最後の項目を除くどの項目もパッケージでなければいけない。 最後の項目は、モジュールまたはパッケージであり得るが、 直前の項目の中で定義されるクラスや関数や変数であってはいけない。

 
6.4.1 パッケージから * を輸入する

ところで利用者が from Sound.Effects import * と書いたら、 何が起こるだろうか? 理想的には、何らかの方法でファイルシステムが調べられ、 そのパッケージにどんな下位モジュールがあるかが見つけ出され、 そしてそれらすべてが輸入される、ということを期待したいところだろう。 あいにく、この操作は Mac と Windows のプラットフォームではうまく働かない。 それらのファイルシステムは必ずしもファイル名の大文字小文字について正確な 情報を持っているわけではないからだ! これらのプラットフォームには、ファイル ECHO.PY を モジュール echo として、Echo として、 それとも ECHO として輸入すべきかどうかを知る確かな方法が ない。(たとえば Windows 95 には、すべてのファイル名を、最初の文字を 大文字にして表示するという困ったクセがある)。 DOS の 8+3 のファイル名制限は、 別の興味深い問題を長いモジュール名に対して追加している。

唯一の解決策は、パッケージの著者がパッケージの索引を明示的に用意するという 方法だ。 import 文は次の規約を使う。すなわち、 もしもパッケージの __init__.py コード が __all__ という名前のリストを定義しているなら、 そのリストは、from package import * に出会ったときに輸入すべき モジュール名のリストであると解釈される。 新しいバージョンのパッケージをリリースする際に このリストを最新に保つことは、パッケージの著者の責任だ。 パッケージの著者は、もしも自分のパッケージから * を輸入するという利用法を 認めないならば、そのリストをサポートしないことにしてもよい。 例として、ファイル Sounds/Effects/__init__.py は次の コードを収めているかもしれない。

__all__ = ["echo", "surround", "reverse"]

これは from Sound.Effects import *Sound パッケージの うち名前を挙げられた三つの下位モジュールを輸入するだろうということを意味する。

もしも __all__ が定義されていなければ、 文 from Sound.Effects import * は、どの下位モジュールも パッケージ Sound.Effects から現在の名前空間の中へ輸入しない。 それはただ (何とかしてその初期化コード __init__.py を実行して) パッケージ Sound.Effects が輸入されたということを確立し、 そのパッケージで定義されている名前を何であれ輸入するだけだ。 これには __init__.py で定義された名前 (とそこで陽にロードされた 下位モジュール) が含まれる。 また、以前の import 文で陽にロードされていたそのパッケージの下位モジュール も含まれる。以下のコードを考える。

import Sound.Effects.echo
import Sound.Effects.surround
from Sound.Effects import *

この例では、echo モジュールと surround モジュールが、 現在の名前空間に輸入される。 なぜなら、それらは、from...import 文が実行される時、 Sound.Effects パッケージの中で定義されているからだ。 (これは __all__ が定義されているときにも働く)。

モジュールやパッケージから * を輸入するというやり方は、 しばしば読みにくいコードにしてしまうため、 一般的には、眉をひそめるものであることに注意しよう。 しかし、対話セッションで打鍵量を節約するために利用することはよいし、 モジュールによっては特定のパターンに従った名前だけを輸出するように 設計されているものもある。

from パッケージ import 特定の下位モジュール」を使うことに 何も不適切さはない、ということを意識しよう! 実際、これは推奨される記法だ。ただし、輸入をするモジュールが、 別々のパッケージからの同じ名前の下位モジュールを使わなくてはならない ときは、この限りではない。

6.4.2 パッケージ内での参照

下位モジュールどうしが互いに参照しあう必要がしばしばある。 たとえば、 surround モジュールが echo モジュールを使うかもしれない。 実際、このような参照はとてもよくあることなので、 import 文は、標準のモジュール検索パスを見る前に、 まず取り囲んでいるパッケージを見る。 こうして、surround モジュールは 単純に import echo とか from echo import echofilter を使う ことができる。 もしも輸入されるモジュールが現在のパッケージ (現在のモジュールを、 下位モジュールとしているパッケージ) に見つからなければ、 import 文は、与えられた名前をもつトップレベルのモジュールを探す。

(例の中の Sound パッケージのように) パッケージが下位パッケージへと 構造化されているとき、兄弟パッケージの下位モジュールを参照する 短縮記法はない -- 下位パッケージのフルネームを使わなければならない。 たとえば、もしも モジュール Sound.Filters.vocoder が、 Sound.Effects パッケージの echo モジュールを 使う必要があるなら、 from Sound.Effects import echo を使うことはできる。

6.4.3 複数ディレクトリ中のパッケージ

パッケージは __path__ というもう一つ特別な属性をサポートしている。 この属性はファイル中のコードが実行される前にパッケージの __init__.py を保持するディレクトリーの名前を含んでいるリストで初期化される。 この変数は変更可能だ。値の変更は、パッケージに含まれているモジュールお よびサブパッケージの検索に影響する。

この機能はほとんどの場合必要ではないが、パッケージで見つかったモジュー ルのセットを拡張するために使用することができる。



... 実行される6.1
実際には関数定義もまた「実行」される「文」であり、 その実行は関数名をモジュールのグローバル記号表に入れる。
See About this document... for information on suggesting changes.