Pythonのパッケージの基本も押さえる特集:Visual Studioで始めるPythonプログラミング(3/4 ページ)

» 2016年11月25日 05時00分 公開
[かわさきしんじInsider.NET編集部]

__init__.pyファイルの__all__変数

 ところで、前回はインポートの形式として「from モジュール名 import *」を取り上げた。これはモジュールに含まれる全ての要素をローカルスコープに導入するものだ。この形式のインポートはパッケージについても以下のようにして同様に使える。ここでemailパッケージはPythonに標準で組み込まれているパッケージであり、電子メール関連の処理を行う複数のモジュールで構成されている。前回も述べたように、モジュールやパッケージに含まれているものを全て無鉄砲にインポートするのはよろしくないが、ここでは例としてこれを行っている。

from email import *
dir()


emailモジュールのインポート

 [Interactive]ウィンドウでの実行結果は次のようになる(改行は適宜挿入したもの)。

>>> from email import *
>>> dir()
['__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__',
'base64mime', 'charset', 'encoders', 'errors', 'feedparser', 'generator',
'header', 'iterators', 'message', 'message_from_binary_file',
'message_from_bytes', 'message_from_file', 'message_from_string', 'mime',
'parser', 'quoprimime', 'utils']


emailパッケージから全てをインポート

 これと同様なことを先ほどのmypackageについて行うとどうなるだろうか。これを([Interactive]ウィンドウの環境をリセットしてから)試した結果が以下だ。

>>> from mypackage import *
>>> dir()  # mypackageが表示されない
['__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__']
>>> mypackage  # mypackageという名前は定義されていない
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'mypackage' is not defined


自作パッケージで同じことを試してみると……

 Pythonのチュートリアルドキュメントの「6.4.1. パッケージから * を import する」には「パッケージの __init__.py コードに __all__ という名前のリストが定義されていれば、 from package import * が現れたときに import すべきモジュール名のリストとして使う」「もしも __all__ が定義されていなければ、実行文 from sound.effects import * は、パッケージ sound.effects の全てのサブモジュールを現在の名前空間の中へ import しません」などと書いてある。

 要するに、「from パッケージ import *」を実行したときに、パッケージ中のどのモジュールをインポートさせるかはパッケージの作者が明示的に指定をしなければならず、そのためには__init__.pyファイルの中で__all__変数にインポートするものを指定する必要があるということだ。

 そこで、今まで空だった__init__.pyファイルを編集してみることにしよう。といっても、ここでは次の1行を追加するだけだ。

__all__ = ["mymodule1"]


「from mypackage import *」でインポートされるものを指定(mypackage\__init__.pyファイル)

 __all__変数にはインポートさせたいモジュールを要素としたリストを代入する。以上のコードを書いてから、先ほどと同じことをしてみると次のようになる。

>>> from mypackage import *
hello from mypackage.mymodule1
>>> dir()
['__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__',
'mymodule1']


mymodule1がローカルスコープに導入された

 ここでパッケージにmymodule2.pyファイルを追加してみよう。

mypackageパッケージにmymodule2.pyファイルを追加 mypackageパッケージにmymodule2.pyファイルを追加

 mymodule2.pyファイルにはmymodule1.pyファイルと同様にインポート時にメッセージを表示し、同じくメッセージを表示するだけの関数fooを定義してある。

print("hello from module2 in mypackage")

def foo():
  print("this is mypackage.mymodule2.foo speaking")


mypackage\mymodule2.pyファイルの内容

 この状況で([Interactive]ウィンドウをリセットして)「from mypackage import *」を実行した結果を以下に示す。

>>> from mypackage import *
hello from mypackage.mymodule1  # 読み込まれたのはmymodule1のみ
>>> dir()
['__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__',
'mymodule1']
>>> from mypackage import mymodule2  # mymodule2を明示的にインポート
hello from module2 in mypackage
>>> mymodule2.foo()
this is mypackage.mymodule2.foo speaking


__init__.pyファイルに記述していないモジュールは「from mypackage import *」ではインポートされない

 __init__.pyファイルの__all__変数ではmymodule2モジュールをインポートするような記述は行っていないので、このパッケージにはmymodule1/mymodule2の2つのモジュールがあるにもかかわらず「from mypackage import *」でインポートされない。このように__init__.pyファイルで設定を行っておけば、自分のパッケージを誰か別の人が使うときに安心して(あるいは開発者が意図した形で)「from パッケージ名 import *」を実行できるようになる。

 本稿の最後に、パッケージがパッケージを含んでいる場合についても簡単に見ておこう。

Copyright© Digital Advantage Corp. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。