6. モジュール¶
Python インタプリタを終了させ、再び起動すると、これまでに行ってきた定義 (関数や変数) は失われています。ですから、より長いプログラムを書きたいなら、テキストエディタを使ってインタプリタへの入力を用意しておき、手作業の代わりにファイルを入力に使って動作させるとよいでしょう。この作業を スクリプト (script) の作成と言います。プログラムが長くなるにつれ、メンテナンスを楽にするために、スクリプトをいくつかのファイルに分割したくなるかもしれません。また、いくつかのプログラムで書いてきた便利な関数について、その定義をコピーすることなく個々のプログラムで使いたいと思うかもしれません。
こういった要求をサポートするために、Python では定義をファイルに書いておき、スクリプトの中やインタプリタの対話インスタンス上で使う方法があります。このファイルを モジュール (module) と呼びます。モジュールにある定義は、他のモジュールや main モジュール (実行のトップレベルや電卓モードでアクセスできる変数の集まりを指します) に import (取り込み) することができます。
モジュールは Python の定義や文が入ったファイルです。ファイル名はモジュール名に接尾語 .py
がついたものになります。モジュールの中では、(文字列の) モジュール名をグローバル変数 __name__
で取得できます。例えば、お気に入りのテキストエディタを使って、現在のディレクトリに以下の内容のファイル fibo.py
を作成してみましょう:
# Fibonacci numbers module
def fib(n): # write Fibonacci series up to n
a, b = 0, 1
while b < n:
print b,
a, b = b, a+b
def fib2(n): # return Fibonacci series up to n
result = []
a, b = 0, 1
while b < n:
result.append(b)
a, b = b, a+b
return result
次に Python インタプリタに入り、モジュールを以下のコマンドで import しましょう:
>>> 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. モジュールについてもうすこし¶
モジュールには、関数定義に加えて実行文を入れることができます。これらの実行文はモジュールを初期化するためのものです。これらの実行文は、インポート文の中で 最初に モジュール名が見つかったときにだけ実行されます。[1] (ファイルがスクリプトとして実行される場合も実行されます。)
各々のモジュールは、自分のプライベートなシンボルテーブルを持っていて、モジュールで定義されている関数はこのテーブルをグローバルなシンボルテーブルとして使います。したがって、モジュールの作者は、ユーザのグローバル変数と偶然的な衝突が起こる心配をせずに、グローバルな変数をモジュールで使うことができます。一方、自分が行っている操作をきちんと理解していれば、モジュール内の関数を参照するのと同じ表記法 modname.itemname
で、モジュールのグローバル変数をいじることもできます。
モジュールが他のモジュールを import することもできます。 import
文は全てモジュールの(さらに言えばスクリプトでも)先頭に置きますが、これは慣習であって必須ではありません。 import されたモジュール名は import を行っているモジュールのグローバルなシンボルテーブルに置かれます。
import
文には、あるモジュール内の名前を、import を実行しているモジュールのシンボルテーブル内に直接取り込むという変型があります。例えば:
>>> from fibo import fib, fib2
>>> fib(500)
1 1 2 3 5 8 13 21 34 55 89 144 233 377
この操作は、import の対象となるモジュール名をローカルなシンボルテーブル内に取り入れることはありません (従って上の例では、 fibo
は定義されません)。
モジュールで定義されている名前を全て import するという変型もあります:
>>> from fibo import *
>>> fib(500)
1 1 2 3 5 8 13 21 34 55 89 144 233 377
上の操作は、アンダースコア (_
) で開始する名前以外の全ての名前を import します。
一般的には、モジュールやパッケージから *
を import するというやり方には賛同できません。というのは、この操作を行うとしばしば可読性に乏しいコードになるからです。しかし、対話セッションでキータイプの量を減らすために使うのは構わないでしょう。
モジュール名の後に as
が続いていた場合は、 as
の後ろの名前を直接、インポートされたモジュールが束縛します。
>>> import fibo as fib
>>> fib.fib(500)
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377
これは実質的には import fibo
と同じ方法でモジュールをインポートしていて、唯一の違いはインポートしたモジュールが fib
という名前で取り扱えるようになっていることです。
このインポート方法は from
が付いていても使え、同じ効果が得られます:
>>> from fibo import fib as fibonacci
>>> fibonacci(500)
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377
注釈
実行効率上の理由で、各モジュールはインタープリタの 1 セッションごとに 1 回だけ import されます。従って、モジュールを修正した場合には、インタープリタを再起動させなければなりません – もしくは、その場で手直ししてテストしたいモジュールが 1 つだった場合には、例えば reload(modulename)
のように reload()
を使ってください。
6.1.1. モジュールをスクリプトとして実行する¶
Python モジュールを
python fibo.py <arguments>
と実行すると、__name__
に __main__
が設定されている点を除いて import したときと同じようにモジュール内のコードが実行されます。つまりモジュールの末尾に:
if __name__ == "__main__":
import sys
fib(int(sys.argv[1]))
このコードを追加することで、このファイルが import できるモジュールであると同時にスクリプトとしても使えるようになります。なぜならモジュールが "main" ファイルとして起動されたときだけ、コマンドラインを解釈するコードが実行されるからです:
$ python fibo.py 50
1 1 2 3 5 8 13 21 34
モジュールが import された場合は、そのコードは実行されません:
>>> import fibo
>>>
この方法はモジュールに便利なユーザインターフェースを提供したり、テストのために (スクリプトをモジュールとして起動しテストスイートを実行して) 使われます。
6.1.2. モジュール検索パス¶
spam
という名前のモジュールをインポートするとき、インタープリターはまずその名前のビルトインモジュールを探します。見つからなかった場合は、 spam.py
という名前のファイルを sys.path
にあるディレクトリのリストから探します。 sys.path
は以下の場所に初期化されます:
- 入力されたスクリプトのあるディレクトリ (あるいはカレントディレクトリ)。
PYTHONPATH
(ディレクトリ名のリスト。シェル変数のPATH
と同じ構文)。- インストールごとのデフォルト
初期化された後、 Python プログラムは sys.path
を修正することができます。スクリプトファイルを含むディレクトリが検索パスの先頭、標準ライブラリパスよりも前に追加されます。なので、ライブラリのディレクトリにあるファイルよりも、そのディレクトリにある同じ名前のスクリプトが優先してインポートされます。これは、標準ライブラリを意図して置き換えているのでない限りは間違いのもとです。より詳しい情報は 標準モジュール を参照してください。
6.1.3. "コンパイル" された Python ファイル¶
たくさんの標準モジュールを使うような短いプログラムの起動時間を大きく高速化するために、 spam.py
が見つかったディレクトリに spam.pyc
という名前のファイルがあった場合には、このファイルをモジュール spam
の "バイトコンパイルされた" バージョンであると仮定します。 spam.pyc
を生成するのに使われたバージョンの spam.py
のファイル修正時刻が spam.pyc
に記録されており、この値が一致しなければ spam.pyc
ファイルは無視されます。
通常、 spam.pyc
ファイルを生成するために何かをする必要はありません。 spam.py
が無事コンパイルされると、常にコンパイルされたバージョンを spam.pyc
へ書き出すよう試みます。この試みが失敗してもエラーにはなりません。何らかの理由でファイルが完全に書き出されなかった場合、作成された smap.pyc
は無効であるとみなされ、それ以後無視されます。 spam.pyc
ファイルの内容はプラットフォームに依存しないので、 Python のモジュールのディレクトリは異なるアーキテクチャのマシン間で共有することができます。
エキスパート向けのTips:
Python インタプリタを
-O
フラグ付きで起動すると、最適化されたコードが生成されて.pyo
ファイルに保存されます。最適化機構は今のところあまり役に立っていません。最適化機構はassert
文とSET_LINENO
命令を除去しているだけです。-O
を使うと、 すべての バイトコード (bytecode) が最適化されます。.pyc
ファイルは無視され、.py
ファイルは最適化されたバイトコードにコンパイルされます。二つの
-O
フラグ (-OO
) を Python インタプリタへ渡すと、バイトコードコンパイラは、まれにプログラムが正しく動作しなくなるかもしれないような最適化を実行します。現状では、ただ__doc__
文字列をバイトコードから除去して、よりコンパクトな.pyo
ファイルにするだけです。この文字列が利用できることをあてにしているプログラムがあるかもしれないので、自分の行っている操作が何かわかっているときにだけこのオプションを使うべきです。.pyc
ファイルや.pyo
ファイルから読み出されたとしても、プログラムは.py
ファイルから読み出されたときより何ら高速に動作するわけではありません。.pyc
ファイルや.pyo
ファイルで高速化されるのは、読み込まれるときの速度だけです。スクリプトの名前をコマンドラインで指定して実行した場合、そのスクリプトのバイトコードが
.pyc
や.pyo
に書き出されることはありません。従って、スクリプトのほとんどのコードをモジュールに移し、そのモジュールを import する小さなブートストラップスクリプトを作れば、スクリプトの起動時間を短縮できるときがあります。.pyc
または.pyo
ファイルの名前を直接コマンドラインに指定することもできます。一つのモジュールについて、ファイル
spam.py
のないspam.pyc
(-O
を使ったときはspam.pyo
) があってもかまいません。この仕様は、Python コードでできたライブラリをリバースエンジニアリングがやや困難な形式で配布するために使えます。compileall
は、.pyc
ファイル (または-O
を使ったときは.pyo
ファイル) をディレクトリ内の全てのモジュールに対して生成することができます。
6.2. 標準モジュール¶
Python は標準モジュールライブラリを同梱していて、別の Python ライブラリリファレンスというドキュメントで解説しています。幾つかのモジュールは言語のコアにはアクセスしないものの、効率や、システムコールなどOSの機能を利用するために、インタープリター内部にビルトインされています。そういったモジュールセットはまたプラットフォームに依存した構成オプションです。例えば、 winreg
モジュールは Windows システムでのみ提供されています。 1つ注目に値するモジュールとして、 sys
モジュールは、全ての Python インタープリターにビルトインされています。 sys.ps1
と sys.ps2
という変数は一次プロンプトと二次プロンプトに表示する文字列を定義しています:
>>> import sys
>>> sys.ps1
'>>> '
>>> sys.ps2
'... '
>>> sys.ps1 = 'C> '
C> print 'Yuck!'
Yuck!
C>
これらの二つの変数は、インタプリタが対話モードにあるときだけ定義されています。
変数 sys.path
は文字列からなるリストで、インタプリタがモジュールを検索するときのパスを決定します。 sys.path
は環境変数 PYTHONPATH
から得たデフォルトパスに、 PYTHONPATH
が設定されていなければ組み込みのデフォルト値に設定されます。標準的なリスト操作で変更することができます:
>>> import sys
>>> sys.path.append('/ufs/guido/lib/python')
6.3. dir()
関数¶
組込み関数 dir()
は、あるモジュールがどんな名前を定義しているか調べるために使われます。 dir()
はソートされた文字列のリストを返します:
>>> import fibo, sys
>>> dir(fibo)
['__name__', 'fib', 'fib2']
>>> dir(sys)
['__displayhook__', '__doc__', '__excepthook__', '__name__', '__package__',
'__stderr__', '__stdin__', '__stdout__', '_clear_type_cache',
'_current_frames', '_getframe', '_mercurial', 'api_version', 'argv',
'builtin_module_names', 'byteorder', 'call_tracing', 'callstats',
'copyright', 'displayhook', 'dont_write_bytecode', 'exc_clear', 'exc_info',
'exc_traceback', 'exc_type', 'exc_value', 'excepthook', 'exec_prefix',
'executable', 'exit', 'flags', 'float_info', 'float_repr_style',
'getcheckinterval', 'getdefaultencoding', 'getdlopenflags',
'getfilesystemencoding', 'getobjects', 'getprofile', 'getrecursionlimit',
'getrefcount', 'getsizeof', 'gettotalrefcount', 'gettrace', 'hexversion',
'long_info', 'maxint', 'maxsize', 'maxunicode', 'meta_path', 'modules',
'path', 'path_hooks', 'path_importer_cache', 'platform', 'prefix', 'ps1',
'py3kwarning', 'setcheckinterval', 'setdlopenflags', 'setprofile',
'setrecursionlimit', 'settrace', 'stderr', 'stdin', 'stdout', 'subversion',
'version', 'version_info', 'warnoptions']
引数がなければ、 dir()
は現在定義している名前を列挙します:
>>> a = [1, 2, 3, 4, 5]
>>> import fibo
>>> fib = fibo.fib
>>> dir()
['__builtins__', '__name__', '__package__', 'a', 'fib', 'fibo', 'sys']
変数、モジュール、関数、その他の、すべての種類の名前をリストすることに注意してください。
dir()
は、組込みの関数や変数の名前はリストしません。これらの名前からなるリストが必要なら、標準モジュール __builtin__
で定義されています:
>>> import __builtin__
>>> dir(__builtin__)
['ArithmeticError', 'AssertionError', 'AttributeError', 'BaseException',
'BufferError', 'BytesWarning', 'DeprecationWarning', 'EOFError',
'Ellipsis', 'EnvironmentError', 'Exception', 'False', 'FloatingPointError',
'FutureWarning', 'GeneratorExit', 'IOError', 'ImportError', 'ImportWarning',
'IndentationError', 'IndexError', 'KeyError', 'KeyboardInterrupt',
'LookupError', 'MemoryError', 'NameError', 'None', 'NotImplemented',
'NotImplementedError', 'OSError', 'OverflowError',
'PendingDeprecationWarning', 'ReferenceError', 'RuntimeError',
'RuntimeWarning', 'StandardError', 'StopIteration', 'SyntaxError',
'SyntaxWarning', 'SystemError', 'SystemExit', 'TabError', 'True',
'TypeError', 'UnboundLocalError', 'UnicodeDecodeError',
'UnicodeEncodeError', 'UnicodeError', 'UnicodeTranslateError',
'UnicodeWarning', 'UserWarning', 'ValueError', 'Warning',
'ZeroDivisionError', '_', '__debug__', '__doc__', '__import__',
'__name__', '__package__', 'abs', 'all', 'any', 'apply', 'basestring',
'bin', 'bool', 'buffer', 'bytearray', 'bytes', 'callable', 'chr',
'classmethod', 'cmp', 'coerce', 'compile', 'complex', 'copyright',
'credits', 'delattr', 'dict', 'dir', 'divmod', 'enumerate', 'eval',
'execfile', 'exit', 'file', 'filter', 'float', 'format', 'frozenset',
'getattr', 'globals', 'hasattr', 'hash', 'help', 'hex', 'id', 'input',
'int', 'intern', 'isinstance', 'issubclass', 'iter', 'len', 'license',
'list', 'locals', 'long', 'map', 'max', 'memoryview', 'min', 'next',
'object', 'oct', 'open', 'ord', 'pow', 'print', 'property', 'quit',
'range', 'raw_input', 'reduce', 'reload', 'repr', 'reversed', 'round',
'set', 'setattr', 'slice', 'sorted', 'staticmethod', 'str', 'sum', 'super',
'tuple', 'type', 'unichr', 'unicode', 'vars', 'xrange', 'zip']
6.4. パッケージ¶
Packages are a way of structuring Python’s module namespace by using "dotted
module names". For example, the module name A.B
designates a submodule
named B
in a package named A
. Just like the use of modules saves the
authors of different modules from having to worry about each other’s global
variable names, the use of dotted module names saves the authors of multi-module
packages like NumPy or the Python Imaging Library from having to worry about
each other’s module names.
音声ファイルや音声データを一様に扱うためのモジュールのコレクション ("パッケージ") を設計したいと仮定しましょう。 音声ファイルには多くの異なった形式がある (通常は拡張子、 例えば .wav
, .aiff
, .au
などで認識されます) ので、増え続ける様々なファイル形式を相互変換するモジュールを、 作成したりメンテナンスしたりする必要があるかもしれません。 また、 音声データに対して実行したい様々な独自の操作 (ミキシング、 エコーの追加、 イコライザ関数の適用、 人工的なステレオ効果の作成など) があるかもしれません。 そうなると、 こうした操作を実行するモジュールを果てしなく書くことになるでしょう。 以下に (階層的なファイルシステムで表現した) パッケージの構造案を示します:
sound/ Top-level package
__init__.py Initialize the sound package
formats/ Subpackage for file format conversions
__init__.py
wavread.py
wavwrite.py
aiffread.py
aiffwrite.py
auread.py
auwrite.py
...
effects/ Subpackage for sound effects
__init__.py
echo.py
surround.py
reverse.py
...
filters/ Subpackage for filters
__init__.py
equalizer.py
vocoder.py
karaoke.py
...
パッケージを import する際、 Python は sys.path
上のディレクトリを検索して、トップレベルのパッケージの入ったサブディレクトリを探します。
あるディレクトリを、パッケージが入ったディレクトリとしてPython に扱わせるには、ファイル __init__.py
が必要です。このファイルを置かなければならないのは、 string
のようなよくある名前のディレクトリにより、モジュール検索パスの後の方で見つかる正しいモジュールが意図せず隠蔽されてしまうのを防ぐためです。最も簡単なケースでは __init__.py
はただの空ファイルで構いませんが、 __init__.py
ではパッケージのための初期化コードを実行したり、後述の __all__
変数を設定してもかまいません。
パッケージのユーザは、個々のモジュールをパッケージから import することができます。例えば:
import sound.effects.echo
この操作はサブモジュール sound.effects.echo
をロードします。このモジュールは、以下のように完全な名前で参照しなければなりません。
sound.effects.echo.echofilter(input, output, delay=0.7, atten=4)
サブモジュールを import するもう一つの方法を示します:
from sound.effects import echo
これもサブモジュール echo
をロードし、 echo
をパッケージ名を表す接頭辞なしで利用できるようにします。従って以下のように用いることができます:
echo.echofilter(input, output, delay=0.7, atten=4)
さらにもう一つのバリエーションとして、必要な関数や変数を直接 import する方法があります:
from sound.effects.echo import echofilter
この操作も同様にサブモジュール echo
をロードしますが、 echofilter()
を直接利用できるようにします:
echofilter(input, output, delay=0.7, atten=4)
from package import item
を使う場合、 item はパッケージ package のサブモジュール (またはサブパッケージ) でもかまいませんし、関数やクラス、変数のような、 package で定義されている別の名前でもかまわないことに注意してください。 import
文はまず、 item がパッケージ内で定義されているかどうか調べます。定義されていなければ、 item はモジュール名であると仮定して、モジュールをロードしようと試みます。もしモジュールが見つからなければ、 ImportError
が送出されます。
反対に、 import item.subitem.subsubitem
のような構文を使った場合、最後の subsubitem
を除く各要素はパッケージでなければなりません。最後の要素はモジュールかパッケージにできますが、一つ前の要素で定義されているクラスや関数や変数にはできません。
6.4.1. パッケージから * を import する¶
それでは、ユーザが from sound.effects import *
と書いたら、どうなるのでしょうか?理想的には、何らかの方法でファイルシステムが調べられ、そのパッケージにどんなサブモジュールがあるかを調べ上げ、全てを import する、という処理を望むことでしょう。これには長い時間がかかってしまうこともありますし、あるサブモジュールを import することで、そのモジュールが明示的に import されたときのみ発生して欲しい副作用が起きてしまうかもしれません。
唯一の解決策は、パッケージの作者にパッケージの索引を明示的に提供させる というものです。 import
文の使う規約は、パッケージの __init__.py
コードに __all__
という名前のリストが定義されていれば、 from package import *
が現れたときに import すべきモジュール名のリストとして使う、というものです。 パッケージの新バージョンがリリースされるときにリストを最新の状態に更新するのは パッケージの作者の責任となります。 自分のパッケージから * を import するという使い方が考えられないならば、 パッケージの作者はこの使い方をサポートしないことにしてもかまいません。 例えば、ファイル sound/effects/__init__.py
には、次のような コードを入れてもよいかもしれません:
__all__ = ["echo", "surround", "reverse"]
この例では、 from sound.effects import *
とすると、 sound
パッケージから指定された 3つのサブモジュールが import されることになっている、ということを意味します。
もしも __all__
が定義されていなければ、実行文 from sound.effects import *
は、パッケージ sound.effects
の全てのサブモジュールを現在の名前空間の中へ import しません 。この文は単に(場合によっては初期化コード __init__.py
を実行して) パッケージ sound.effects
が import されたということを確認し、そのパッケージで定義されている名前を全て import するだけです。 import される名前には、 __init__.py
で定義された名前 (と、明示的にロードされたサブモジュール) が含まれます。パッケージのサブモジュールで、以前の import
文で明示的にロードされたものも含みます。以下のコードを考えてください:
import sound.effects.echo
import sound.effects.surround
from sound.effects import *
上の例では、 echo
と surround
モジュールが現在の名前空間に import されます。これらのモジュールは from...import
文が実行された際に sound.effects
内で定義されているからです。 (この機構は __all__
が定義されているときにも働きます。)
特定のモジュールでは import *
を使ったときに、特定のパターンに従った名前のみを公開 (export) するように設計されてはいますが、それでもやはり製品のコードでは良いことではないと考えます。
from package import specific_submodule
を使っても何も問題はないことに留意してください!実際この表記法は、import を行うモジュールが他のパッケージと同じ名前を持つサブモジュールを使わなければならない場合を除いて推奨される方式です。
6.4.2. パッケージ内参照¶
サブモジュール同士で互いに参照を行う必要がしばしば起こります。例えば、 surround
モジュールは echo
モジュールを使うかもしれません。このような参照はよくあることなので、 import
文を実行すると、まず最初に import 文の入っているパッケージを検索し、その後になって標準のモジュール検索パスを見に行きます。なので、 surround
モジュールは単に import echo
や from echo import echofilter
を使うことができます。 import されたモジュールが現在のパッケージ(現在のモジュールをサブモジュールにしているパッケージ) 内に見つからなかった場合、 import
文は指定した名前のトップレベルのモジュールを検索します。
パッケージが (前述の例の sound
パッケージのように) サブパッケージの集まりに構造化されている場合、絶対 import を使って兄弟関係にあるパッケージを参照できます。例えば、モジュール sound.filters.vocoder
で sound.effects
パッケージの echo
モジュールを使いたいとすると、 from sound.effects import echo
を使うことができます。
Python 2.5 からは、上で説明した暗黙の相対importに加えて、明示的な相対importを from module import name
の形式の import 文で利用できます。この明示的な相対 import では、先頭のドットで現在および親パッケージを指定します。 surround
モジュールの例では、以下のように記述できます。
from . import echo
from .. import formats
from ..filters import equalizer
明示的であってもそうでなくても、相対 import は現在のモジュール名をベースにすることに注意してください。メインモジュールの名前は常に "__main__"
なので、 Python アプリケーションのメインモジュールとして利用されることを意図しているモジュールでは絶対 import を利用するべきです。
6.4.3. 複数ディレクトリ中のパッケージ¶
パッケージはもう一つ特別な属性として __path__
をサポートしています。この属性は、パッケージの __init__.py
中のコードが実行されるよりも前に、 __init__.py
の収められているディレクトリ名の入ったリストになるよう初期化されます。この変数は変更することができます。変更を加えると、以降そのパッケージに入っているモジュールやサブパッケージの検索に影響します。
この機能はほとんど必要にはならないのですが、パッケージ内存在するモジュール群を拡張するために使うことができます。
注記
[1] | 実際には、関数定義も '実行' される '文' です。モジュールレベルの関数定義を実行すると、関数名はモジュールのグローバルなシンボルテーブルに入ります。 |