プログラムの規模が大きくなり、モジュールファイル(.py)の数が増えてくると、それらを一つのディレクトリ(フォルダ)にまとめて整理したくなります。
Pythonでは、複数のモジュールをディレクトリ単位でまとめたものを**「パッケージ(Package)」**と呼びます。パッケージ化することで、機能ごとに名前空間を分離し、大規模なアプリケーションでも整理された状態を保つことができます。
この記事では、独自のパッケージを作成する手順と、パッケージの挙動を制御する __init__.py ファイルの役割について解説します。
パッケージの基本構成
Pythonでパッケージを作成するには、基本的には以下の2つのステップを踏みます。
- フォルダを作成する(フォルダ名がパッケージ名になります)。
- そのフォルダの中に、モジュールファイル(
.py)と、__init__.pyという特殊なファイルを配置する。
ディレクトリ構造の例
例として、計算機能を提供する math_tools というパッケージを作成する場合の構成です。
project_root/
│
├─ main.py <-- 実行するスクリプト
│
└─ math_tools/ <-- これがパッケージ
│
├─ __init__.py <-- パッケージ初期化ファイル
├─ basic.py <-- モジュール1
└─ geometry.py <-- モジュール2
補足:
__init__.pyについて Python 3.3以降では__init__.pyがなくてもパッケージとして認識されます(名前空間パッケージ)が、通常のパッケージとして明示的に扱うため、また初期化処理を行うために、現在でも作成するのが一般的です。中身は空でも構いません。
1. モジュールの作成
まず、パッケージの中身となるモジュールを作成します。
math_tools/basic.py
def add(a, b):
"""単純な足し算"""
return a + b
def subtract(a, b):
"""単純な引き算"""
return a - b
math_tools/geometry.py
class Rectangle:
"""長方形クラス"""
def __init__(self, width, height):
self.width = width
self.height = height
def area(self):
return self.width * self.height
2. パッケージの利用(通常のインポート)
作成したパッケージを利用するには、main.py から以下のようにインポートします。ドット(.)を使って パッケージ名.モジュール名 のように階層を辿ります。
main.py
# 方法1: モジュールを指定してインポート
from math_tools import basic, geometry
# 利用
result = basic.add(10, 5)
rect = geometry.Rectangle(10, 20)
print(f"足し算: {result}")
print(f"面積: {rect.area()}")
実行結果:
足し算: 15
面積: 200
3. __init__.py を使ったインポートの簡略化
上記の例では、利用する際に basic や geometry といった内部のモジュール名を意識してインポートする必要がありました。
__init__.py を編集することで、パッケージ外部に対して「どのような機能を公開するか」を制御し、インポートをシンプルにすることができます。
math_tools/__init__.py
# パッケージ内のモジュールから、特定の関数やクラスを
# パッケージの直下に読み込む
from .basic import add
from .geometry import Rectangle
# subtract は公開しない(という意図)
このように __init__.py に記述すると、利用側からはモジュール名を飛ばして、パッケージから直接関数やクラスをインポートできるようになります。
main.py (改善版)
# パッケージから直接読み込めるようになる
import math_tools
# または from math_tools import add, Rectangle
# math_tools.add() としてアクセス可能
# (math_tools.basic.add ではなく)
result = math_tools.add(5, 8)
rect = math_tools.Rectangle(4, 5)
print(f"足し算(短縮): {result}")
print(f"面積(短縮): {rect.area()}")
実行結果:
足し算(短縮): 13
面積(短縮): 20
__init__.py が「受付窓口」の役割を果たし、内部の basic.py や geometry.py の存在を利用者から隠蔽(カプセル化)することで、使いやすいライブラリを設計できます。
まとめ
- 複数のモジュールをディレクトリにまとめることで「パッケージ」を作成できます。
- ディレクトリには
__init__.pyを置くのが一般的です。 from パッケージ import モジュールで利用します。__init__.pyにfrom .モジュール import 機能を記述することで、パッケージ直下に機能を公開し、利用側のインポート記述を短縮できます。
