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 a < n:
        print(a, end=' ')
        a, b = b, a+b
    print()

def fib2(n):
    """Return Fibonacci series up to n."""
    result = []
    a, b = 0, 1
    while a < n:
        result.append(a)
        a, b = b, a+b
    return result

次に Python インタプリタに入り、モジュールを以下のコマンドで import しましょう:

>>> import fibo

この操作では、fibo で定義された関数の名前を直接現在の namespace (詳細は Python のスコープと名前空間 を参照してください)に追加することはありません。単にモジュール名 fibo だけを名前空間に追加します。関数にはモジュール名を使ってアクセスします:

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

関数を度々使うのなら、ローカルな名前に代入できます:

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

6.1. モジュールについてもうすこし

モジュールには、関数定義に加えて実行文を入れることができます。これらの実行文はモジュールを初期化するためのものです。これらの実行文は、インポート文の中で 最初に モジュール名が見つかったときにだけ実行されます。[1] (ファイルがスクリプトとして実行される場合も実行されます。)

各々のモジュールは、自分のプライベートな名前空間を持っていて、モジュールで定義されている関数はこのテーブルをグローバルな名前空間として使います。したがって、モジュールの作者は、ユーザのグローバル変数と偶然的な衝突が起こる心配をせずに、グローバルな変数をモジュールで使うことができます。一方、自分が行っている操作をきちんと理解していれば、モジュール内の関数を参照するのと同じ表記法 modname.itemname で、モジュールのグローバル変数をいじることもできます。

モジュールは他のモジュールをインポートできます。 import 文はモジュール(さらに言えばスクリプトでも)の先頭に置きますが、これは慣習であって必須ではありません。インポートされたモジュール名は、モジュールのトップレベル(関数やクラスの外)に書いてあれば、モジュールのグローバルな名前空間に置かれます。

import 文には、あるモジュール内の名前を、import を実行しているモジュールの名前空間内に直接取り込むという変型があります。例えば:

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

この操作は、import の対象となるモジュール名をローカルな名前空間内に取り入れることはありません (従って上の例では、 fibo は定義されません)。

モジュールで定義されている名前を全て import するという変型もあります:

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

この書き方ではアンダースコア (_) で始まるものを除いてすべての名前をインポートします。殆どの場面で、Python プログラマーはこの書き方を使いません。未知の名前がインタープリターに読み込まれ、定義済みの名前を上書きしてしまう可能性があるからです。

一般的には、モジュールやパッケージから * を 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 つだった場合には、例えば import importlib; importlib.reload(modulename) のように importlib.reload() を使ってください。

6.1.1. モジュールをスクリプトとして実行する

Python モジュールを

python fibo.py <arguments>

と実行すると、モジュール内のコードは import したときと同じように実行されますが、 __name__ には文字列 "__main__" が設定されます。 この違いを利用するために、モジュールの末尾に次のコードを追加します。

if __name__ == "__main__":
    import sys
    fib(int(sys.argv[1]))

このコードを追加することで、このファイルが import できるモジュールであると同時にスクリプトとしても使えるようになります。なぜならモジュールが "main" ファイルとして起動されたときだけ、コマンドラインを解釈するコードが実行されるからです:

$ python fibo.py 50
0 1 1 2 3 5 8 13 21 34

モジュールが import された場合は、そのコードは実行されません:

>>> import fibo
>>>

この方法はモジュールに便利なユーザインターフェースを提供したり、テストを行ったりするためによく使われます。 後者では、モジュールをスクリプトとして実行するとテストスイートが実行されます。

6.1.2. モジュール検索パス

spam という名前のモジュールをインポートするとき、インタープリタはまずその名前の組み込みモジュールを探します。モジュール名の一覧は sys.builtin_module_names にあります。 見つからなかった場合は、 spam.py という名前のファイルを sys.path にあるディレクトリのリストから探します。 sys.path は次の場所を基に初期化されます。

  • 入力されたスクリプトのあるディレクトリ (あるいはファイルが指定されなかったときはカレントディレクトリ)。

  • PYTHONPATH (ディレクトリ名のリスト。シェル変数の PATH と同じ構文)。

  • インストール方法に依存したデフォルト(慣例として site-packages ディレクトリーが含まれ、site モジュールによって処理される)。

詳細は sys.path モジュール検索パスの初期化 を参照してください。

注釈

シンボリックリンクをサポートするファイルシステム上では、入力されたスクリプトのあるディレクトリはシンボリックリンクをたどった後に計算されます。言い換えるとシンボリックリンクを含むディレクトリはモジュール検索パスに追加 されません。

初期化された後、 Python プログラムは sys.path を修正することができます。スクリプトファイルを含むディレクトリが検索パスの先頭、標準ライブラリパスよりも前に追加されます。なので、ライブラリのディレクトリにあるファイルよりも、そのディレクトリにある同じ名前のスクリプトが優先してインポートされます。これは、標準ライブラリを意図して置き換えているのでない限りは間違いのもとです。より詳しい情報は 標準モジュール を参照してください。

6.1.3. "コンパイル" された Python ファイル

モジュールの読み込みを高速化するため、Python はコンパイル済みの各モジュールを __pycache__ ディレクトリの module.version.pyc ファイルとしてキャッシュします。ここで version はコンパイルされたファイルのフォーマットを表すもので、一般的には Python のバージョン番号です。例えば、CPython のリリース 3.3 の、コンパイル済みの spam.py は __pycache__/spam.cpython-33.pyc としてキャッシュされるでしょう。この命名の慣習により、Python の異なる複数のリリースやバージョンのコンパイル済みモジュールが共存できます。

Python はソースの変更日時をコンパイル済みのものと比較し、コンパイル済みのものが最新でなくなり再コンパイルが必要になっていないかを確認します。これは完全に自動で処理されます。また、コンパイル済みモジュールはプラットフォーム非依存なため、アーキテクチャの異なるシステム間で同一のライブラリを共有することもできます。

Python は2つの場合にキャッシュのチェックを行いません。ひとつは、コマンドラインから直接モジュールが読み込まれた場合で、常に再コンパイルされ、結果を保存することはありません。2つめは、ソース・モジュールのない場合で、キャッシュの確認を行いません。ソースのない (コンパイル済みのもののみの) 配布をサポートするには、コンパイル済みモジュールはソース・ディレクトリになくてはならず、ソース・ディレクトリにソース・モジュールがあってはいけません。

エキスパート向けのTips:

  • コンパイル済みモジュールのサイズを小さくするために、Python コマンドに -O または -OO スイッチを使うことができます。-O スイッチは assert ステートメントを除去し、-OO スイッチは assert ステートメントと __doc__ 文字列を除去します。いくつかのプログラムはこれらの除去されるものに依存している可能性があるため、自分が何をしているかを理解しているときに限ってこれらのオプションを使うべきです。"最適化" されたモジュールは opt- タグを持ち、通常のコンパイル済みモジュールよりサイズが小さくなります。将来のリリースでは最適化の影響が変わる可能性があります。

  • .pyc ファイルから読み出されたとしても、プログラムは .py ファイルから読み出されたときより何ら高速に動作するわけではありません。 .pyc ファイルで高速化されるのは、読み込みにかかる時間だけです。

  • compileall モジュールを使ってディレクトリ内の全てのモジュールに対して .pyc ファイルを作ることができます。

  • この処理に関する詳細は、判定のフローチャートを含めて、PEP 3147 に記載されています。

6.2. 標準モジュール

Python は標準モジュールのライブラリを同梱していて、別のドキュメント「Python ライブラリリファレンス」(以下「ライブラリリファレンス」) で解説しています。 一部のモジュールはインタープリターに組み込まれていて、言語の中核には含まれない操作を提供します。 これらが組み込まれているのは、効率を高めたり、 システムコールなどのオペレーティングシステムの基本機能を利用できるようにしたりするためです。 どのモジュールを組み込むかは構成オプションで指定し、動作するプラットフォームにも依存します。 例えば、winreg モジュールは Windows システムでのみ提供されています。 特に注目したいのが、すべての Python インタープリターに組み込まれている sys モジュールです。 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)
['__breakpointhook__', '__displayhook__', '__doc__', '__excepthook__',
 '__interactivehook__', '__loader__', '__name__', '__package__', '__spec__',
 '__stderr__', '__stdin__', '__stdout__', '__unraisablehook__',
 '_clear_type_cache', '_current_frames', '_debugmallocstats', '_framework',
 '_getframe', '_git', '_home', '_xoptions', 'abiflags', 'addaudithook',
 'api_version', 'argv', 'audit', 'base_exec_prefix', 'base_prefix',
 'breakpointhook', 'builtin_module_names', 'byteorder', 'call_tracing',
 'callstats', 'copyright', 'displayhook', 'dont_write_bytecode', 'exc_info',
 'excepthook', 'exec_prefix', 'executable', 'exit', 'flags', 'float_info',
 'float_repr_style', 'get_asyncgen_hooks', 'get_coroutine_origin_tracking_depth',
 'getallocatedblocks', 'getdefaultencoding', 'getdlopenflags',
 'getfilesystemencodeerrors', 'getfilesystemencoding', 'getprofile',
 'getrecursionlimit', 'getrefcount', 'getsizeof', 'getswitchinterval',
 'gettrace', 'hash_info', 'hexversion', 'implementation', 'int_info',
 'intern', 'is_finalizing', 'last_traceback', 'last_type', 'last_value',
 'maxsize', 'maxunicode', 'meta_path', 'modules', 'path', 'path_hooks',
 'path_importer_cache', 'platform', 'prefix', 'ps1', 'ps2', 'pycache_prefix',
 'set_asyncgen_hooks', 'set_coroutine_origin_tracking_depth', 'setdlopenflags',
 'setprofile', 'setrecursionlimit', 'setswitchinterval', 'settrace', 'stderr',
 'stdin', 'stdout', 'thread_info', 'unraisablehook', 'version', 'version_info',
 'warnoptions']

引数がなければ、 dir() は現在定義している名前を列挙します:

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

変数、モジュール、関数、その他の、すべての種類の名前をリストすることに注意してください。

dir() は組込みの関数や変数の名前を列挙しません。 その名前の一覧が必要な場合は、定義元の標準モジュール builtins を調べます。

>>> import builtins
>>> dir(builtins)
['ArithmeticError', 'AssertionError', 'AttributeError', 'BaseException',
 'BlockingIOError', 'BrokenPipeError', 'BufferError', 'BytesWarning',
 'ChildProcessError', 'ConnectionAbortedError', 'ConnectionError',
 'ConnectionRefusedError', 'ConnectionResetError', 'DeprecationWarning',
 'EOFError', 'Ellipsis', 'EnvironmentError', 'Exception', 'False',
 'FileExistsError', 'FileNotFoundError', 'FloatingPointError',
 'FutureWarning', 'GeneratorExit', 'IOError', 'ImportError',
 'ImportWarning', 'IndentationError', 'IndexError', 'InterruptedError',
 'IsADirectoryError', 'KeyError', 'KeyboardInterrupt', 'LookupError',
 'MemoryError', 'NameError', 'None', 'NotADirectoryError', 'NotImplemented',
 'NotImplementedError', 'OSError', 'OverflowError',
 'PendingDeprecationWarning', 'PermissionError', 'ProcessLookupError',
 'ReferenceError', 'ResourceWarning', 'RuntimeError', 'RuntimeWarning',
 'StopIteration', 'SyntaxError', 'SyntaxWarning', 'SystemError',
 'SystemExit', 'TabError', 'TimeoutError', 'True', 'TypeError',
 'UnboundLocalError', 'UnicodeDecodeError', 'UnicodeEncodeError',
 'UnicodeError', 'UnicodeTranslateError', 'UnicodeWarning', 'UserWarning',
 'ValueError', 'Warning', 'ZeroDivisionError', '_', '__build_class__',
 '__debug__', '__doc__', '__import__', '__name__', '__package__', 'abs',
 'all', 'any', 'ascii', 'bin', 'bool', 'bytearray', 'bytes', 'callable',
 'chr', 'classmethod', 'compile', 'complex', 'copyright', 'credits',
 'delattr', 'dict', 'dir', 'divmod', 'enumerate', 'eval', 'exec', 'exit',
 'filter', 'float', 'format', 'frozenset', 'getattr', 'globals', 'hasattr',
 'hash', 'help', 'hex', 'id', 'input', 'int', 'isinstance', 'issubclass',
 'iter', 'len', 'license', 'list', 'locals', 'map', 'max', 'memoryview',
 'min', 'next', 'object', 'oct', 'open', 'ord', 'pow', 'print', 'property',
 'quit', 'range', 'repr', 'reversed', 'round', 'set', 'setattr', 'slice',
 'sorted', 'staticmethod', 'str', 'sum', 'super', 'tuple', 'type', 'vars',
 'zip']

6.4. パッケージ

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

音声ファイルや音声データを統一的に扱うためのモジュールの集まり (「パッケージ」) を設計したいとします。 音声ファイルには多くの形式があり、通常は .wav、.aiff、.au などの拡張子で見分けます。 そのため、形式を相互変換するモジュールを作成・保守し、その数を増やしていく必要があるかもしれません。 また、ミキシング、エコーの追加、イコライザ機能の適用、人工的なステレオ効果の作成など、音声データに行いたい操作もさまざまです。 こうした操作を実行するためのモジュールも、次々に書くことになるでしょう。 パッケージの構造は、例えば次のようにできます (階層的なファイルシステムで表しています):

sound/                          トップレベルのパッケージ
      __init__.py               soundパッケージの初期化
      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
              ...

パッケージを import する際、Python は sys.path 上のディレクトリを検索し、 パッケージに対応するサブディレクトリを探します。

ファイルを含むディレクトリをパッケージとしてPython に扱わせるには、ファイル __init__.py が必要です(より高度な機能 namespace package を使う場合を除く)。 これにより、 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.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 * とすると、名前の挙がった 3つのサブモジュールが sound.effects パッケージから import される、ということです。

注意点として、サブモジュールはローカルな名前で隠されることがあります。例として、 reverse 関数を sound/effects/__init__.py に足すと、 from sound.effects import * では echo と surround の2サブモジュールだけ import されます。 reverse サブモジュールは import されません 。それはローカルに定義された reverse 関数で隠されたので:

__all__ = [
    "echo",      # 'echo.py' ファイルを参照する
    "surround",  # 'surround.py' ファイルを参照する
    "reverse",   # !!! 'reverse' 関数を参照する !!!
]

def reverse(msg: str):  # <-- この名前は 'from sound.effects import *' を実行したときに
    return msg[::-1]    #     サブモジュールの 'reverse.py' を隠してしまう

もしも __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. パッケージ内参照

パッケージが (前述の例の sound パッケージのように) サブパッケージの集まりに構造化されている場合、 絶対 import を使って兄弟関係にあるパッケージのサブモジュールを参照できます。 例えば、モジュール sound.filters.vocoder で sound.effects パッケージの echo モジュールが必要な場合、 from sound.effects import echo が使えます。

また、明示的な相対importを from module import name の形式の import 文で利用できます。この明示的な相対 import では、先頭のドットで現在および親パッケージを指定します。 surround モジュールの例では、以下のように記述できます:

from . import echo
from .. import formats
from ..filters import equalizer

Note that relative imports are based on the name of the current module's package. Since the main module does not have a package, modules intended for use as the main module of a Python application must always use absolute imports.

脚注