Modules

↑を読みたい気持ちをグッとこらえて (Pythonの勉強に疲れたら読もう) Pythonチュートリアルを進めます。


閑話休題。ここではModuleというとっても重要な概念について勉強します。といってもそんなに特殊なものではありません。いわゆるモジュールとまったく同じ意味で使われています。Pythonでは関数や変数などの定義をファイルに保存するとそのファイル名 (.pyは除く) がモジュール名となって、別のモジュールやインタープリターにインポート出来るのです。たとえば次のようなモジュールを定義します (fibo.py) 。

# Fibonacci numbers module

def fib(n):
    a, b = 0, 1
    while b < n:
        print b,
        a, b = b, a + b

def fib2(n):
    result = []
    a, b = 0, 1
    while b < n:
        result.append(b)
        a, b = b, a + b
    return result


インタープリターからインポートして使ってみます。

>>> import 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'


なお、module名.__name__でModuleの名前を参照することが出来ます。App Engineのチュートリアルを試した方はこの__name__は見たことあると思います。こんな使い方をしていました。

if __name__ == "__main__":
    main()


これは自分のモジュール名が__main__かどうかをチェックしているんですね。でもファイル名は__main__.pyなわけではありませんけど・・・この理由は後ほど。

More on Modules

まず最初は基本的なModuleのインポート方法について。さきほどimport文を使ってインポートしましたが、App Engineを勉強している人には次のような書き方の方が馴染み深いのではないでしょうか。

>>> from fibo import fib, fib2


これはfiboというModuleからfib、fib2という関数をインポートすることを意味します。こうすることでfibo.fibとかfibo.fib2と書かなくても済むのです。

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


と書くことも出来ますが、これだとこの中でどの関数が使われているのかよく分からなくなります。Javaでも同じですよね。あまりよいプラクティスとは言えません。

Executing modules as scripts

Moduleとして作成したPythonコードを実行することを考えます。

% python fibo.py


Moduleを実行する時、先ほど説明した__name__という変数にはfiboではなく__main__という特殊な名前が割り当てられます。これを利用して次のようにfibo.pyを書き換えます。

# ↑で書いた内容と同じ内容なので省略

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


つまりこのModuleが実行された時は引数を使ってフィボナッチ数列を表示するわけです。

% python fibo.py 1000
1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987


App Engineでよく見かけるコードの意味がこれで分かりました。

The Module Search Path

Moduleを探すパスはこんな感じになっています。


自分で汎用モジュールなどを作った場合はPYTHONPATHに指定するのがいいでしょうね。その際は標準モジュールと名前がかち合わないように気をつける必要があります。かち合うとインポート時にエラーが発生します。

"Compiled" Python files

先ほどのfiboモジュールをインポートしたり、実行した結果、fibo.pyと同じ場所にfibo.pycというファイルが出来ているのに気づきます。これはfibo.pyをバイトコンパイルしたバージョンです。自動的に生成されるんですね。自動的に生成されるので、もちろんfibo.pyが更新されたら再度バイトコンパイルが実行されるようになっています。なお、このバイトコンパイルはimport時のロード時間軽減には効果を発揮しますが、実行速度はバイトコンパイルしないものと変わらないようです。

A program doesn’t run any faster when it is read from a .pyc or .pyo file than when it is read from a .py file

http://docs.python.org/tutorial/modules.html#compiled-python-files

Standard Modules

こちらは標準ライブラリについて。でも標準ライブラリの勉強は別の場所で行うのでここでは割愛。ていうかここにはそんな大したことは書いてないし。

The dir() Function

ここではdir()という便利な関数に関して。dir()は指定されたモジュールの定義 (シンボル) を全て出力してくれます。

>>> import fibo
>>> dir(fibo)
['__builtins__', '__doc__', '__file__', '__name__', '__package__', 'fib', 'fib2']


引数なしで指定すると参照可能なシンボル全てを見ることが可能です。

>>> a = [1, 2, 3]
>>> dir()
['__builtins__', '__doc__', '__name__', '__package__', 'a', 'fibo']


直前で定義したリストaも含まれています。

Packages

パッケージは複数のモジュールを束ねる単位です。たとえばでたらめにこんな感じの階層構造を作ってみます。

% ls
hogehoge1/
% ls hogehoge1/
__init__.py  hogehoge2/
% ls hogehoge1/hogehoge2/
__init__.py  test1.py   test2.py


test1.pyはこんな感じ。

# test1.py

def test():
    print "test1.test()"


test2.pyはこちら。

# test2.py

def test():
    print "test2.test()"


ディレクトリにある__init__.pyは空ファイルです。中にモジュールの初期化コードを書くことも出来ます。この__init__.pyがモジュール (サブモジュール) であることをPythonに教えています。では早速使ってみましょう。

>>> import hogehoge1.hogehoge2.test1      # このimportだとフルネームが必要
>>> hogehoge1.hogehoge2.test1.test()
test1.test()
>>> from hogehoge1.hogehoge2 import test1 # このimportだとモジュール名が必要
>>> test1.test()
test1.test()
>>> from hogehoge1.hogehoge2.test2 import test  # このimportだと間数名だけでOK
>>> test()
test2.test()
Importing * From a Package

ここではimport文で「*」を使うことを考えます。普通に考えると

from hogehoge1.hogehoge2 import *


と書くとhogehoge1.hogehoge2パッケージ以下の全てのモジュールをインポートしそうですが、実際に試してみると

>>> from hogehoge1.hogehoge2 import *
>>> test1.test()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'test1' is not defined


not definedと出ています。つまりimport出来ていないのです。「*」を使ってimportするには先ほど紹介した__init__.pyファイルを使います。__init__.pyファイル内で__all__というリストを定義することで「*」を使ったimportを制御出来ます。たとえば

__all__ = ["test1"]


と書くとhogehoge1.hogehoge2パッケージのtest1モジュールだけimportされるようになります。

>>> from hogehoge1.hogehoge2 import *
>>> test1.test()
test1.test
>>> test2.test()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'test2' is not defined


もちろんtest2モジュールのimportは許可していませんのでエラーになります。

Intra-package References

こちらはパッケージ内の相対的な位置関係でimportする方法です。たとえば↑の例で言うとhogehoge1/hogehoge2/test1.pyを以下のように変更することが可能です。

# test1.py
import test2

def test():
    print "test1.test()"
    test2.test()


test2モジュールはtest1モジュールと同じ場所にあるのでパッケージ名 (hogehoge1.hogehoge2) を指定しなくてもよいわけです。

>>> import test1
>>> test1.test()
test1.test()
test2.test()


またPython2.5からは親パッケージの参照に「..」という指定が出来るようになったそうです。たとえば、↑の例でhogehoge1/hogehoge3/test3.pyを作成したとします。

# test3.py

def test()
    print "test3.test()"


もちろん__init__.pyも作成します (中身は空でOKです) 。そしてhogehoge1/hogehoge2/test2.pyを以下のように書き換えます。

#test2.py
from ..hogehoge3 import test3

def test():
    print "test2.test()"
    test3.test()


つまりtest1.test() → test2.test() → test3.test()というように呼び出しがネストしている構造です。

>>> from hogehoge1.hogehoge2 import test1
>>> test1.test()
test1.test()
test2.test()
test3.test()


なお、この場合インタープリター実行場所を注意して下さい。hogehoge1/hogehoge2で実行するとここがトップレベルになってしまうため、..hogehoge3という相対モジュール指定は不正になってしまいます (トップレベルよりも上には行けないため) 。

Packages in Multiple Directories

各パッケージディレクトリの__init__.pyが実行される前に__path__というリストに各パッケージのパスが格納されます。この__path__の中身を変えることが出来るみたいです。そうするとimportするモジュールを別の場所のモジュールに変更するなど出来るそうです。でも使うと訳が分からなくなってしまいそうですね。