# Pythonのモジュールとパッケージ：import、pip、venv、ライブラリをわかりやすく

URL: https://skillaria.top/ja/guides/python/moduli-python

Pythonのモジュールは拡張子 .py のファイル、パッケージはモジュールをまとめたフォルダ、ライブラリはその集まりです。import でモジュールを読み込み、外部のライブラリは pip（または uv）で仮想環境 venv の中にインストールします。仮想環境は、プロジェクトごとにライブラリのバージョンを分け、互いに干渉しないようにする独立したフォルダです。

Pythonのモジュールは、コードを書いた普通のファイルです。`import` を使うと、そこから関数やクラスを取り出せます。モジュールをまとめるとパッケージになり、パッケージの集まりがライブラリです。さらに、異なるプロジェクトのライブラリが互いに干渉しないように、外部ライブラリは仮想環境 venv の中にインストールします。ここでは、この一連の流れを順に解説します。import の動作、パッケージの構造、pipとvenvの使い方、そしてPython 3.15で追加された遅延インポートです。

## モジュール、パッケージ、ライブラリの違い

| 用語 | 意味 | 例 |
| --- | --- | --- |

| モジュール | 1つの `.py` ファイル。モジュール名はファイル名から拡張子を除いたもの | `categories.py` → `import categories` |

| パッケージ | `__init__.py` を含み、モジュールを入れたフォルダ | `expenses/report.py` → `from expenses.report import build` |

| ライブラリ | 特定の目的のための、モジュールとパッケージの完成したセット | `requests`、`pandas`、標準の `pathlib` |

| 配布パッケージ（PyPIのパッケージ） | pipでインストールされるアーカイブ | `pip install requests` |

会話の中では「ライブラリ」「パッケージ」「モジュール」が混同されがちですが、それで問題ありません。技術的には、`import` は常にモジュールかパッケージを読み込みます。一方、pipはPyPIから配布パッケージをインストールし、その中にパッケージが入っています。

## importの仕組み

importにはいくつかの書き方があり、どれも実際のコードで使われています。

```
import math                    # モジュール全体、math.sqrt と書く
from math import sqrt, pi      # 個別の名前を取り出す
import datetime as dt          # 別名を付ける
from collections import Counter as C

print(math.sqrt(16), sqrt(9), pi)
print(dt.date.today())
```

大きなライブラリには、慣習的な別名があります。例えば `import numpy as np`、`import pandas as pd` です。`from module import *` は、名前空間を散らかし、名前がどこから来たのか分からなくなるので、使わない方が良いでしょう。

### importが実際に行うこと

1. `sys.modules` のキャッシュを確認します。すでに読み込み済みなら、そのまま返します。
2. キャッシュになければ、`sys.path` に並ぶフォルダからファイルを探します。順番は、実行中のスクリプトのフォルダ、標準ライブラリ、仮想環境の site-packages です。
3. 見つかったファイルを、上から下へ丸ごと実行します。
4. モジュールのオブジェクトをキャッシュに入れ、名前に結びつけます。

ここから2つの実践的な結論が出ます。同じモジュールを2回目にimportしても、コードはもう一度実行されないため、ほとんど時間がかかりません。また、モジュールのトップレベルにあるコード（`print` や重い計算を含む）は、importされた時点で必ず実行されます。

```
import sys
for p in sys.path:
    print(p)
print("math" in sys.modules)
```

### if __name__ == "__main__"

importはファイルを実行するので、「スクリプトとして起動された」場合と「モジュールとして読み込まれた」場合を区別する方法が必要です。そのためにあるのが変数 `__name__` です。ファイルを直接実行すると `"__main__"` になり、importされると、モジュール名が入ります。

```
# categories.py
def guess(title: str) -> str:
    return "食費" if "カフェ" in title else "その他"

if __name__ == "__main__":
    print(guess("カフェ近くの店"))   # python categories.py で実行したときだけ表示
```

パッケージには別の方法もあります。パッケージの中に `__main__.py` を置き、`python -m expenses` で実行します。

## Pythonの標準モジュール

Pythonには「バッテリー込み」の思想があり、数百の標準モジュールが、インストールせずにすぐ使えます。よく使うものは次のとおりです。

| モジュール | 用途 |
| --- | --- |

| `os`、`sys`、`pathlib`、`shutil` | システム、パス、ファイル |

| `json`、`csv`、`pickle` | データ形式 |

| `datetime`、`time`、`calendar` | 日付と時刻 |

| `math`、`random`、`statistics`、`fractions` | 数値 |

| `re`、`string` | テキスト処理 |

| `collections`、`itertools`、`functools` | データ構造とイテレータ |

| `logging`、`argparse`、`subprocess` | ログ、コマンドライン引数、プログラムの起動 |

| `asyncio`、`threading` | 非同期処理とスレッド |

標準ライブラリのモジュール名の一覧は、`sys.stdlib_module_names`（Python 3.10以降）で確認できます。モジュールに何が含まれているかは、`dir(math)` と `help(math)` で調べられます。

## 独自のパッケージの構成

モジュールが増えてきたら、パッケージにまとめます。よく使われるフォルダ構成はsrcレイアウトです。

```
expenses-project/
├── pyproject.toml
└── src/
    └── expenses/
        ├── __init__.py
        ├── cli.py
        ├── parsing.py
        ├── categories.py
        └── report.py
```

パッケージ内のモジュールは、パッケージ名で（`from expenses.categories import guess`）、または相対的に（`from .categories import guess`）互いをimportします。相対importは、パッケージの中でのみ動きます。スクリプトとして直接実行されたファイルでは動きません。

## pip：ライブラリのインストール

外部ライブラリはPyPIに登録されていて、Pythonに付属するpipというツールでインストールします。pipは、インタープリターを指定して呼び出すのが確実です。そうすれば、そのライブラリは、実行に使うPythonにしっかり入ります。

```
python -m pip install requests          # インストール
python -m pip install "pandas>=2.3"     # バージョンを指定
python -m pip install --upgrade requests
python -m pip uninstall requests        # アンインストール
python -m pip list                      # インストール済みの一覧
python -m pip show requests             # バージョンと依存関係
python -m pip freeze > requirements.txt
python -m pip install -r requirements.txt
```

Windowsでは、`python` の代わりにランチャーの `py` をよく使います。pipが見つからない場合は、標準モジュールで導入できます。`python -m ensurepip --upgrade` を実行してください。

### よく使われるPythonライブラリ

PyPIには数十万のパッケージがありますが、ほとんどのプロジェクトで使われるのは、同じ短いリストです。まずはこれから始めるのがよいでしょう。

| 用途 | ライブラリ |
| --- | --- |

| HTTPリクエストとAPI | `requests`、`httpx` |

| データ分析と表 | `pandas`、`numpy` |

| グラフ | `matplotlib` |

| Webサービス | `fastapi`、`django`、`flask` |

| テスト | `pytest` |

| 画像 | `pillow`（`PIL` としてimportする） |

インストール時の名前と、import時の名前が一致しない場合があります。`pip install pillow` と書きますが、コードでは `from PIL import Image` と書きます。`opencv-python` は、`cv2` としてimportします。インストール直後に `import` が失敗する場合は、そのパッケージのドキュメントで、import名を確認してください。

### LinuxでのPythonライブラリのインストール

最近のDebianやUbuntuでは、システムのPythonに `pip install` を実行すると、`externally-managed-environment` というエラーになります（PEP 668）。これは保護のための仕組みで、システムのPythonはOSのパッケージマネージャが管理しているため、pipで壊してはいけないのです。正しい解決策は `--break-system-packages` を使うことではなく、仮想環境を作ることです。

## venv：仮想環境

仮想環境とは、独自のインタープリター（へのリンク）と、独自のsite-packagesを持つ独立したフォルダです。そこにインストールしたライブラリは、そのプロジェクトからしか見えません。たとえば、ある案件ではDjango 4を、別の案件ではDjango 5を使うといったことが、衝突せずにできます。

`venv` モジュールはPythonに標準で含まれています。別途インストールする必要はありません。ただし、DebianやUbuntuでは、システムパッケージの `python3-venv` が必要な場合があります。

```
# .venv フォルダに仮想環境を作る
python -m venv .venv

# 有効化: LinuxとmacOS
source .venv/bin/activate
# 有効化: Windows PowerShell
.venv\Scripts\Activate.ps1

# 以後、pipは .venv の中にパッケージを入れる
python -m pip install requests
python -c "import sys; print(sys.prefix)"

# 仮想環境から抜ける
deactivate
```

有効化すると、ターミナルの行の先頭に `(.venv)` が表示されます。仮想環境のフォルダはgitにコミットしないでください（`.gitignore` に `.venv/` を追加します）。また、別のマシンへ持ち運ぶものでもありません。代わりに、依存関係の一覧を保存しておき、仮想環境を作り直します。PowerShellで有効化スクリプトの実行が禁止されている場合は、現在のユーザーに対して許可します。`Set-ExecutionPolicy -Scope CurrentUser RemoteSigned` を実行してください。

### uvとpyproject.toml

最近のプロジェクトでは、依存関係を `pyproject.toml` に記述します。講座で使うuvは、仮想環境の作成とインストールを1つにまとめます。`uv add pandas` はパッケージをダウンロードし、`pyproject.toml` に記録して、正確なバージョンを `uv.lock` に固定します。チームのメンバーはプロジェクトをクローンして `uv sync` を実行するだけで、まったく同じ環境が手に入ります。

```
[project]
name = "expenses"
version = "0.1.0"
requires-python = ">=3.15"
dependencies = [
    "pandas>=2.3",
]

[project.scripts]
expenses = "expenses.cli:main"
```

## Python 3.15の遅延インポート（PEP 810）

このテーマにおける3.15の最大の新機能は、`lazy` キーワードです。重いライブラリは読み込みに時間がかかります。講座の計測では、`python:3.15-slim` のイメージで通常の `import pandas` に約415ミリ秒かかりましたが、`lazy import pandas` は約13ミリ秒でした。`--help` のためだけに起動するコマンドラインツールでは、この差は非常に大きくなります。

```
lazy import pandas as pd
lazy from expenses.report import build_report

def main() -> None:
    ...
    df = pd.read_csv(path)   # ここで初めて pandas を本当に読み込む
```

モジュールの代わりに、名前にはプロキシオブジェクト（`types.LazyImportType`）が入ります。実際のimportは、その名前が最初に使われたときに行われます。使われなければ、時間はまったくかかりません。

### 遅延インポートの制限

- モジュールのトップレベルでのみ使えます。関数、クラス、`try/except` の中で書くと `SyntaxError` になります。
- `lazy from x import *` は禁止です。
- `ModuleNotFoundError` は、起動時ではなく、最初に使われたときに発生します。
- モジュールの副作用（プラグインの登録など）は、後の時点に移動します。

すべてのimportを一括で遅延させるには、`-X lazy_imports=all` オプション、または環境変数 `PYTHON_LAZY_IMPORTS=all` を使います。例外は `sys.set_lazy_imports_filter()` で指定できます。古いバージョンでも動くコードには、モジュール変数 `__lazy_modules__ = ["pandas"]` を使えます。Python 3.15では指定したimportが遅延になり、古いバージョンでは通常のimportとして実行されます。起動時にどこで時間がかかっているかは、`python -X importtime -c "import pandas"` で確認できます。恩恵が大きいのは、短時間で何度も起動されるプログラムです。長時間動くサーバーでは、ほとんど効果がありません。

## よくあるミス

- `ModuleNotFoundError: No module named 'requests'` ― ライブラリが別のPythonにインストールされているか、仮想環境が有効化されていません。同じインタープリターで `python -m pip show requests` を実行して確認します。
- 自作ファイルに `json.py`、`random.py`、`csv.py` などの名前を付けた ― スクリプトのフォルダが `sys.path` の先頭に来るため、標準モジュールが隠されてしまいます。Python 3.13以降では、エラーメッセージで「consider renaming」と提案されます。ファイル名を変更し、`__pycache__` を削除してください。
- 循環インポート（`a.py` が `b.py` を、`b.py` が `a.py` をimportする） ― 共通部分を3つ目のモジュールに移すか、関数の中でimportしてください。
- Pythonのインタープリターの中で `pip install` を実行する（`>>> pip install`） ― `SyntaxError` になります。pipのコマンドはターミナルで実行します。

## まとめ

モジュールはファイル、パッケージはモジュールのフォルダ、ライブラリはそれらの完成したセットです。`import` は、キャッシュと `sys.path` を探し、1回だけ実行します。外部ライブラリは、pipまたはuvを使って、仮想環境venvの中にだけインストールしましょう。そうすれば、プロジェクト同士が干渉せず、環境を再現しやすくなります。講座では、このテーマを実践で扱います。家計簿ツールをパッケージにまとめ、依存関係を管理し、遅延インポートで起動を速くします。

## FAQ

**プロジェクトごとに venv を作る必要がありますか？**

はい。おすすめの方法です。プロジェクトごとにライブラリのバージョンが異なるため、仮想環境を分けると衝突を防げ、システムのPythonも汚れません。

**pip と uv の違いは何ですか？**

pip はパッケージのインストールだけを行います。uv は仮想環境の作成、pyproject.toml への依存関係の記録、ロックファイルによる正確なバージョンの固定も行います。しかも速いです。

**インストール済みのライブラリの一覧を見るには？**

対象の環境で python -m pip list を実行します。pip freeze は同じ内容を requirements.txt の形式で出力します。

**インストールしたモジュールはどこに保存されますか？**

現在の仮想環境の site-packages フォルダです。個々のモジュールの場所は、__file__ 属性で確認できます。例：import requests; print(requests.__file__)

**venv フォルダを別のパソコンに移せますか？**

いいえ。仮想環境はそのマシンのパスとインタープリターに結びついています。移すのは依存関係の一覧で、移動先で仮想環境を作り直します。


---
Source: Skillaria.Top (https://skillaria.top)
