Pythonのパッケージ作成入門:ディレクトリ構成とinit.pyによるインポートの制御

プログラムの規模が大きくなり、モジュールファイル(.py)の数が増えてくると、それらを一つのディレクトリ(フォルダ)にまとめて整理したくなります。

Pythonでは、複数のモジュールをディレクトリ単位でまとめたものを**「パッケージ(Package)」**と呼びます。パッケージ化することで、機能ごとに名前空間を分離し、大規模なアプリケーションでも整理された状態を保つことができます。

この記事では、独自のパッケージを作成する手順と、パッケージの挙動を制御する __init__.py ファイルの役割について解説します。

目次

パッケージの基本構成

Pythonでパッケージを作成するには、基本的には以下の2つのステップを踏みます。

  1. フォルダを作成する(フォルダ名がパッケージ名になります)。
  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 を使ったインポートの簡略化

上記の例では、利用する際に basicgeometry といった内部のモジュール名を意識してインポートする必要がありました。

__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.pygeometry.py の存在を利用者から隠蔽(カプセル化)することで、使いやすいライブラリを設計できます。

まとめ

  • 複数のモジュールをディレクトリにまとめることで「パッケージ」を作成できます。
  • ディレクトリには __init__.py を置くのが一般的です。
  • from パッケージ import モジュール で利用します。
  • __init__.pyfrom .モジュール import 機能 を記述することで、パッケージ直下に機能を公開し、利用側のインポート記述を短縮できます。
よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

私が勉強したこと、実践したこと、してることを書いているブログです。
主に資産運用について書いていたのですが、
最近はプログラミングに興味があるので、今はそればっかりです。

目次