小さなPythonプログラムは1個の.pyファイルでも作れます。しかし、入力処理、計算式、検証、出力が同じファイルへ増え続けると、変更の影響範囲が分かりにくくなります。
そこでPythonでは、処理をモジュールやパッケージへ分けます。さらに外部パッケージを使うプロジェクトでは、仮想環境を作って依存関係を分離します。
この記事では、次の最小構成を作ります。
engineering_project/
├── engineering_calc/
│ ├── __init__.py
│ └── hydraulics.py
└── main.py
特定のIDEには依存せず、Python標準機能とコマンドラインを基準に説明します。
今日の到達点
- モジュールとパッケージの違いを説明できる
importで標準ライブラリと自作モジュールを利用できるif __name__ == "__main__"の役割を理解できるvenvでプロジェクト専用の仮想環境を作れる- 仮想環境内のPythonを指定して
pipを実行できる - 依存関係を記録し、別環境で再現する考え方を理解できる
モジュールはPythonコードを分ける単位
Pythonでは、関数や変数などを定義した.pyファイルをモジュールとして利用できます。
たとえばhydraulics.pyへ油圧計算を分離します。
"""Hydraulic calculation functions."""
def calculate_force_n(
pressure_mpa: float,
area_mm2: float,
) -> float:
"""Return theoretical force in N from MPa and mm²."""
if pressure_mpa <= 0:
raise ValueError("pressure_mpa must be greater than 0")
if area_mm2 <= 0:
raise ValueError("area_mm2 must be greater than 0")
return pressure_mpa * area_mm2
別のファイルから読み込むにはimportを使います。
import hydraulics
force_n = hydraulics.calculate_force_n(14.0, 1000.0)
print(f"Force: {force_n:.1f} N")
実行結果です。
Force: 14000.0 N
hydraulics.calculate_force_nのようにモジュール名を付けると、関数がどこで定義されているか読み取りやすくなります。
importの代表的な書き方
モジュール全体を読み込む
import math
area_mm2 = math.pi * 80.0 ** 2 / 4
print(f"Area: {area_mm2:.3f} mm²")
math.piのように出所が明確です。
必要な名前だけ読み込む
from math import pi
area_mm2 = pi * 80.0 ** 2 / 4
短く書けますが、読み込む名前が多いと出所が分かりにくくなります。
別名を付ける
import math as mathematics
area_mm2 = mathematics.pi * 80.0 ** 2 / 4
別名は、一般的な慣習がある場合や名前の衝突を避ける場合に使います。不必要に独自の略称を増やすと、かえって読みにくくなります。
アスタリスクによる読み込みを避ける
from math import *
この書き方では多数の名前が現在の名前空間へ入り、どこから来た名前か分かりにくくなります。入門段階では、モジュール名または必要な名前を明示します。
標準ライブラリと外部パッケージ
Pythonには、インストール直後から使える標準ライブラリがあります。
import csv
import json
import math
from pathlib import Path
一方、Python本体とは別に配布されるものは、必要に応じてパッケージ管理ツールで導入します。
重要なのは、importとインストールを区別することです。
- インストール:利用する環境へパッケージを配置する
import:実行中のプログラムからモジュールを読み込む
標準ライブラリは通常、追加のpip installなしで読み込めます。外部パッケージは、使用するPython環境へ事前にインストールされている必要があります。
パッケージはモジュールを整理する仕組み
Python公式チュートリアルでは、パッケージをドット区切りのモジュール名で名前空間を構造化する方法として説明しています。
次の構成では、engineering_calcがパッケージ、hydraulics.pyがその中のモジュールです。
engineering_project/
├── engineering_calc/
│ ├── __init__.py
│ └── hydraulics.py
└── main.py
engineering_calc/hydraulics.pyを作ります。
def calculate_force_n(
pressure_mpa: float,
area_mm2: float,
) -> float:
if pressure_mpa <= 0:
raise ValueError("pressure_mpa must be greater than 0")
if area_mm2 <= 0:
raise ValueError("area_mm2 must be greater than 0")
return pressure_mpa * area_mm2
engineering_calc/__init__.pyでは、パッケージの利用者へ公開する名前をまとめられます。
from .hydraulics import calculate_force_n
__all__ = ["calculate_force_n"]
先頭の.は、同じパッケージ内のhydraulicsを表します。
main.pyからは次のように読み込みます。
from engineering_calc import calculate_force_n
def main() -> None:
force_n = calculate_force_n(14.0, 1000.0)
print(f"Force: {force_n:.1f} N")
if __name__ == "__main__":
main()
実行結果です。
Force: 14000.0 N
この構成の主要コードはPython 3.12.14で実行確認済みです。
__name__と直接実行の判定
Pythonのモジュールには__name__という名前があります。
ファイルを直接実行したとき、そのモジュールの__name__は"__main__"になります。一方、別のファイルからインポートした場合は、通常はモジュール名になります。
PI_APPROX = 3.14159
def circle_area_mm2(diameter_mm: float) -> float:
return PI_APPROX * diameter_mm ** 2 / 4
if __name__ == "__main__":
area_mm2 = circle_area_mm2(80.0)
print(f"Self-check: {area_mm2:.3f} mm²")
このファイルを直接実行すると、自己確認コードが動きます。
Self-check: 5026.544 mm²
別ファイルからインポートした場合、if内は実行されません。
import module_demo
area_mm2 = module_demo.circle_area_mm2(80.0)
print(f"Imported: {area_mm2:.3f} mm²")
実行結果です。
Imported: 5026.544 mm²
この判定を使うと、再利用する関数の定義と、直接実行時の入口を同じファイルに置けます。ただし、大規模化したらテストは別ファイルへ分離します。
仮想環境で依存関係を分離する
外部パッケージをシステム全体へ無差別にインストールすると、プロジェクトごとに必要な版が衝突する可能性があります。
venvは、独立したPythonパッケージ群を持つ軽量な仮想環境を作る標準ライブラリです。
プロジェクトのルートで次を実行します。
python -m venv .venv
環境によって起動コマンドがpython3またはpyの場合があります。
python3 -m venv .venv
py -m venv .venv
.venvはよく使われるディレクトリ名ですが、必須の名前ではありません。仮想環境は移動して使い回すものではなく、必要なら再作成できるように依存関係を記録します。
仮想環境を有効化する
macOSやLinuxの代表例です。
source .venv/bin/activate
Windows PowerShellの代表例です。
.venv\Scripts\Activate.ps1
Windowsのコマンドプロンプトでは次のようにします。
.venv\Scripts\activate.bat
有効化は、シェルが参照するPythonとコマンドの優先順位を仮想環境へ切り替える操作です。仮想環境のPythonをフルパスで指定する場合、有効化は必須ではありません。
どのPythonを使っているかは次で確認できます。
python -c "import sys; print(sys.executable)"
仮想環境かどうかをプログラムから確認する例です。
import sys
print(sys.prefix != sys.base_prefix)
仮想環境内なら通常はTrueになります。
終了するときは次を実行します。
deactivate
pipは対象のPythonを明示する
PyPAの公式ガイドでは、仮想環境を作成・有効化してからpipでパッケージをインストールする流れが示されています。
パッケージ管理では、次の形式を使うとpipがどのPythonに属するか明確です。
python -m pip --version
パッケージをインストールする基本形です。
python -m pip install package-name
package-nameは例示用です。実際には、必要なパッケージの公式ドキュメントとPyPI上の配布元を確認して名前を指定します。似た名前の別パッケージを誤って導入しないよう注意してください。
インストール済みパッケージは次で確認できます。
python -m pip list
特定パッケージの情報は次で確認できます。
python -m pip show package-name
依存関係を記録する
別のPCや将来の自分が同じ環境を再現できるよう、必要な依存関係を記録します。
現在の環境を一覧へ出力する方法です。
python -m pip freeze > requirements.txt
記録した依存関係をインストールする例です。
python -m pip install -r requirements.txt
ただし、pip freezeは環境内のインストール済みパッケージを列挙します。開発用ツールまで含む場合があるため、公開プロジェクトでは「直接必要な依存関係」と「固定された完全な環境」を分けて管理する方法もあります。
入門段階では、次を守るだけでも再現性が大きく向上します。
- プロジェクトごとに仮想環境を作る
.venv自体をGitへ登録しない- 必要なパッケージと版をテキストで記録する
- 使用したPythonの版も記録する
- 再作成手順をREADMEへ書く
importできないときの確認順序
ModuleNotFoundErrorが出る
ModuleNotFoundError: No module named 'example'
次を順に確認します。
- モジュール名の綴りは正しいか
- 実行中のPythonは想定した仮想環境か
- 外部パッケージはその環境へインストール済みか
- 自作モジュールは読み込み可能な配置か
- ファイル名が標準ライブラリと衝突していないか
たとえば自作ファイルへmath.pyやjson.pyと名付けると、標準ライブラリと衝突して意図しない読み込みになる可能性があります。
pipで入れたのにimportできない
pipを実行したPythonと、プログラムを実行しているPythonが異なる可能性があります。
python -m pip --version
python -c "import sys; print(sys.executable)"
この2つが同じ仮想環境を指しているか確認します。
循環importが発生する
モジュールAがBを読み、BがAを読む構成では、初期化途中の名前へアクセスして失敗することがあります。
共通処理を第3のモジュールへ移す、責務を見直す、必要な依存方向を一方向にするなど、構造から修正します。
実務へつなげる最小ルール
工学計算やCAD周辺自動化では、次のように分けると再利用しやすくなります。
engineering_project/
├── engineering_calc/
│ ├── __init__.py
│ ├── hydraulics.py
│ ├── units.py
│ └── validation.py
├── tests/
├── main.py
├── requirements.txt
└── README.md
hydraulics.py:圧力、流量、推力などの計算units.py:単位変換validation.py:入力範囲や有限性の検証main.py:入力と出力を接続する入口tests/:計算ロジックの確認requirements.txt:外部依存関係README.md:前提、Python版、実行方法
計算式と画面操作を分けておけば、同じ計算モジュールをコマンドライン、Webツール、CSV処理、CAD自動化などから再利用できます。
練習問題
標準ライブラリを読み込む
mathモジュールを使い、直径50 mmの円面積を求めてください。
import math
diameter_mm = 50.0
area_mm2 = math.pi * diameter_mm ** 2 / 4
print(f"Area: {area_mm2:.3f} mm²")
期待される出力です。
Area: 1963.495 mm²
自作モジュールへ関数を分ける
unit_conversion.pyを作り、L/minをL/sへ変換する関数を定義してください。
def convert_l_min_to_l_s(flow_l_min: float) -> float:
return flow_l_min / 60
別ファイルから読み込みます。
from unit_conversion import convert_l_min_to_l_s
flow_l_s = convert_l_min_to_l_s(120.0)
print(f"Flow: {flow_l_s:.2f} L/s")
期待される出力です。
Flow: 2.00 L/s
仮想環境のPythonを確認する
仮想環境を作成・有効化し、実行中のPythonの場所とpipの所属先を確認してください。
python -m venv .venv
python -c "import sys; print(sys.executable)"
python -m pip --version
確認観点は、Pythonとpipが同じ.venv配下を参照していることです。
まとめ
.pyファイルはモジュールとして再利用できるimport moduleは名前の出所を明確にしやすい- パッケージはモジュールの名前空間を階層化する
__init__.pyでパッケージの初期化や公開する名前を整理できるif __name__ == "__main__"で直接実行時の入口を分けられる- 標準ライブラリと外部パッケージは別物である
venvでプロジェクトごとのパッケージ環境を分離できるpython -m pipは対象のPythonを明示しやすい- 仮想環境そのものではなく、依存関係と再作成手順を記録する
- 計算、検証、入出力をモジュールへ分けると再利用とテストが容易になる
モジュール化の目的は、ファイル数を増やすことではありません。変更理由の異なる処理を分け、同じ計算ロジックを別の入口から再利用できるようにすることです。

