モジュール

モジュール

module とは、 php の require_once に namespace を組み合わせたようなものです。

同じディレクトリに、 foo.py と bar.py という2つのファイルがあるとしましょう。

foo.py:

A = 3

def add(x):
    return x + A

bar.py:

import foo

print(foo.A)  # => 3
print(foo.add(2)) # => 5

bar.py で import foo することにより、 foo.py が foo モジュールとして 読み込まれています。 bar.py の中では foo.py の中のグローバルの要素が、 foo.Xfoo.add のようにして参照できます。

これは、 php の次のようなコードに近いでしょう.

foo.php:

<?php
namespace foo {
    $A = 3;

    function add($x) {
        global $A;
        return $A + $x;
    }
}

bar.php:

<?php
require_once 'foo.php';

echo foo\$A . "\n";
echo foo\add(2) . "\n";

2つの重要な違いを覚えておいてください。

  • Python のモジュールは特殊な namespace ではなく、ただのオブジェクトです。 import foo は foo モジュールオブジェクトを foo という変数に代入しているだけです。
  • Python でグローバル変数を作っても、それはそのモジュール内でのグローバルであり、 他のファイルのグローバル変数と衝突することはありません。他のファイルからは モジュールオブジェクトの属性に見えます。

パッケージ

パッケージとは、他のモジュールを子供に持つことができる モジュールです。

通常のモジュールが、モジュール名=ファイル名となるファイルだったのに対して、 パッケージは通常パッケージ名のディレクトリと、その中の __init__.py という ファイルが実体になります。

foo/__init__.py:

FOO = 1

foo/bar.py:

BAR = 2

baz.py:

import foo.bar
print(foo.FOO) # => 1
print(foo.bar.BAR) # => 2

baz.py の import foo.bar は、次のような処理をします。

  1. foo/__init__.pyfoo モジュールという名前で読み込む。
  2. foo/bar.pyfoo.bar モジュールという名前で読み込む。
  3. foo モジュールオブジェクトの bar という属性に bar オブジェクトを代入する。
  4. baz.py ファイルの foo という変数に foo パッケージを代入する。

ここで重要な注意があります。 もし foo/__init__.pybar という変数を定義した場合、上の手順4番によって その変数は上書きされてしまいます。

一方、 foo/__init__.py の内容が次の様になっていた場合は結果が異なります。

foo/__init__.py:

import foo.bar
FOO = bar
bar = 3

この場合、 baz.py を実行すると次のような順序で実行されます。

  1. baz.py の import foo.bar により、まず foo/__init__.pyfoo パッケージとして実行される。
  2. foo/__init__.py の中の import foo.bar が実行される。 foo パッケージはすでに(読込中であるものの)存在するので、 foo.bar というモジュール名で foo/bar.py が実行される。
  3. foo/bar.py の実行が終わったあと、 foo パッケージに bar 属性として foo.bar モジュールが 代入される。
  4. foo/__init__.pyimport foo.bar の実行が完了し、 foo という変数に、読込中の foo パッケージ自体が代入される。
  5. FOO = bar が実行され、 foo.bar モジュールが FOO という変数にコピーされる。
  6. bar = 3 が実行される。
  7. baz.py の import foo.bar が完了し、 print(foo.FOO)<module 'foo.bar'...> と表示する。
  8. print(foo.bar.BAR) が実行されるものの、 foo.bar は 3 で、 BAR という属性を持たないのでエラーになる。

なので、モジュールとパッケージについて2つの重要な点を覚えておきましょう。

  • モジュールは読み込む順番で動作が異なる可能性がある。
  • パッケージ内の変数は、そのパッケージは以下のサブモジュール名と衝突する可能性がある。

php も require_once の実行順で動作が異なる可能性がありますが、普段はその順序にできるだけ依存しないように プログラムを書いているでしょう。 Python でも同じように、ファイルのグローバルで副作用のある動作をせず、 import の順序によって問題を起こさないようにするするべきです。

パッケージ内の変数とサブモジュールとの名前が衝突しそうになった時は、パッケージの外から その名前でアクセスしたいのがどちらかを考えましょう。上の例で言えば、 baz.py から foo.bar を参照した時に変数側を見せたいのであれば、モジュール側は foo._bar という名前で foo/_bar.py に置きましょう。逆にモジュール側をみせて変数側を隠したいのであれば、 変数名を _bar にしましょう。

外に見せたくないオブジェクトの名前を _ で始めるのは Python で一般的な習慣です。

__name__

foo.py が python foo.py として実行された場合も、 import foo でインポートされた場合も、 そのファイルの中身が実行されるという点では同じですが、自動的に定義される __name__ という変数で区別することができます。

スクリプトとして実行されている場合は __name__'__main__' になり、 モジュールとしてインポートされている時はそのモジュール名になります。

if __name__ == '__main__': という定型句で、スクリプトとして実行することも import することも可能なファイルを作ることができます。 単にスクリプトを書くだけの場合もこうして置くことで、中の便利な関数を 使いたくなったときやテストしたくなった時に import することができます。

他の import 文の書き方

as

import foo.bar as fb と書くと、 foo 変数に foo パッケージを代入する代わりに、 foobar という変数に foo.bar モジュールを代入します。 import が長い時に、その中の要素にアクセスするために毎回 foo.bar と書く代わりに fb と書くことができます。 といっても、短すぎてわかりにくい名前は、他のグローバル変数と同じようにやめましょう。

from ... import

from foo import bar と書くと、 bar という変数に foo.bar モジュールが代入されます。 as と組み合わせて from foo import bar as foobar と書くこともできます。

import foo.bar as bar と違い、 from foo import bar では bar はモジュールである 必要はありません。 foo モジュールの中のクラスや変数など任意の属性を直接インポートできます。

また、服数の要素を一括でインポートする事が出来る点です。次のように書くと、 foo パッケージから fizz, buzz, fizzbuzz の3つをインポートできます。

from foo import (
    fizz,
    buzz,
    fizzbuzz)

インポートする名前を1つずつ列挙する代わりに、 from foo import * のように書くこともできます。 この場合、 foo モジュールが __all__ という変数名で公開する名前のリストを定義していればそれが、 そうでなければ _ で始まる物を除いて全ての名前がインポートされます。

* は便利ですが、特に2つ以上使った場合に、そのファイル内で利用している名前がどこから インポートしたものか判りにくくなってしまいます。1つだけしか使わない、名前をみたら何か ひと目で判るくらい頻繁に利用される場合にだけ使う、など節度を守って使いましょう。

相対 import と絶対 import

Python 2 では import bar が foo パッケージや foo パッケージ内のモジュール (foo.baz など) で 実行された場合、 まず foo.bar モジュールを探し(相対インポート)、無かったら今度は bar モジュールを探します(絶対インポート)。

この暗黙の相対インポートがわかりにくいということで、 Python 3 では禁止され、 import bar は常に bar を指すようになりました。 Python 2 でもファイルの先頭に from __future__ import absolute_import と書くことで常に絶対インポートにすることができます。

その代わりに、明示的な相対 import のための構文が追加されました。 from X import Y の X の部分が ドット1つで始まっていた場合は現在のパッケージ、ドット2つで始まっていた場合は親パッケージから Y を 探します。わかりにくいので例を書きます。 foo.bar パッケージ内にある foo.bar.baz モジュールの 場合、明示的な相対インポートは次のようになります。

from . import egg      # from foo.bar import egg
from .. import egg     # from foo import egg
from .spam import egg  # from foo.bar.spam import egg
from ..spam import egg # from foo.spam import egg

明示的な相対インポートは Python 2 でも使えます。他の __future__ の要素 (division, print_function) とともに積極的に利用して、 Python 3 に備えましょう。

検索パス

import foo.bar を実行するときに、 foo をまずどこから探すかは検索パスで定義されます。 検索パスの実体は sys モジュールにある sys.path というリストです。

通常、ライブラリを pipeasy_install でインストールすると、自動的に Python 起動時にそのライブラリの インストール場所がは自動的に sys.path に登録されるように構成されます。 モジュールを検索するときはこのリストの前から順番に検索されます。

また、スクリプトを実行するときはそのスクリプトのあるディレクトリが、インタラクティブシェルを 起動するときはカレントディレクトリが自動的に sys.path の先頭に追加されます。

その他のディレクトリを検索パスに追加する方法はたくさんありますが、直接的な方法を2つだけ 紹介します。

追加したい検索パスをスクリプト自体が知っている場合は、そのスクリプトで sys.path を編集します。 たとえばあるプロジェクトで、 projname/ と scripts/ というディレクトリがあるばあい、 scripts/ の中のスクリプトは次のように書くことで projname をインポートできます。

import os
import sys
sys.path.append(os.path.dirname(os.path.dirname(__file__)))
import projname

逆に、単にライブラリを使いたいスクリプトがあって、 pip などでインストールされてない ライブラリの場所を教えたい場合は、 PYTHONPATH 環境変数を利用します。

$ PYTHONPATH=$(pwd) scripts/foo.py

どちらも面倒な場合は、 distribute を使った setup.py ファイルを作って、 python setup.py develop コマンドでモジュールをインストールせずにプロジェクトのディレクトリを 直接登録することができます。最小限の setup.py は次のようになります。

from setuptools import setup
setup(packages=['projname'])