Pythonでモジュール(.pyファイル)を複数作成し、それらを一つのまとまりとして管理したいとき、パッケージという概念が登場します。このパッケージを定義するために不可欠なのが、__init__.pyという特別な名前のファイルです。
__init__.pyの役割
__init__.pyは、あるディレクトリがPythonのパッケージであることをPythonに認識させるための、目印となるファイルです。
このファイルがディレクトリ内に存在することで、そのディレクトリ内のモジュールをimport文で呼び出すことができるようになります。
1. パッケージとしての認識
my_projectというディレクトリ内に、module_a.pyとmodule_b.pyというファイルがあるとします。
my_project/
├── main.py
├── my_package/
│ ├── __init__.py
│ ├── module_a.py
│ └── module_b.py
この構造でmy_package内に__init__.pyが存在することで、main.pyから以下のようにmy_package内のモジュールをインポートできます。
# main.py
import my_package.module_a
from my_package import module_b
my_package.module_a.say_hello()
module_b.say_goodbye()
もし__init__.pyがなければ、Pythonはmy_packageを単なる普通のディレクトリと見なし、上記のインポートはModuleNotFoundErrorというエラーになります。
__init__.pyのもう一つの役割
__init__.pyは、単なる目印以上の役割も果たします。このファイルの中身は、パッケージがインポートされたときに最初に実行されるコードです。この特性を利用して、以下のようなことができます。
1. パッケージの初期化
パッケージがインポートされたときに、共通の初期設定(例:ロギング設定、データベース接続など)を行うことができます。
2. 外部への公開設定
__init__.pyの中で他のモジュールの関数やクラスをインポートすることで、パッケージのトップレベルから直接それらを使えるようにできます。
例えば、my_package/module_a.pyにsay_hello()関数、my_package/module_b.pyにsay_goodbye()関数があるとします。
my_package/__init__.py
# 以下の行を追加することで、my_packageをインポートしたときに
# say_helloとsay_goodbyeが直接使えるようになる
from .module_a import say_hello
from .module_b import say_goodbye
これで、main.pyから以下のように書くことができます。
# main.py
from my_package import say_hello, say_goodbye
say_hello()
say_goodbye()
これにより、my_packageの内部構造を隠蔽し、ユーザーはどのモジュールに何が含まれているかを気にせずに、公開された機能だけを利用できるようになります。
まとめ
-
__init__.pyは、そのディレクトリがPythonのパッケージであることを示します。これがなければ、importできません。 -
パッケージがインポートされたときに実行される初期化ファイルとしての役割も持ちます。
-
このファイルを利用して、パッケージの公開インターフェースを定義し、コードの使いやすさを向上させることができます。
Python 3.3以降、__init__.pyがなくても一部のインポートは可能になりましたが、互換性を考慮し、また上記のような機能を活用するためにも、パッケージを作成する際は__init__.pyを含めるのが依然として一般的な習慣です。