基礎

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

更新日: · Skillaria.Top

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リクエストとAPIrequests、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の中にだけインストールしましょう。そうすれば、プロジェクト同士が干渉せず、環境を再現しやすくなります。講座では、このテーマを実践で扱います。家計簿ツールをパッケージにまとめ、依存関係を管理し、遅延インポートで起動を速くします。

よくある質問

プロジェクトごとに 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 フォルダを別のパソコンに移せますか?

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

動画でこのテーマを学ぶ

このテーマはコース「Python 3.15: от новичка до профи」で実践とともに詳しく解説しています。

コースへ