Fullmoon System

Python venvの使い方:作成・有効化からrequirements.txtと本番運用まで

EdwardMoon

Python venvの中心となる機能は、プロジェクトごとにパッケージのインストール先を分離することです。venvはPython標準ライブラリの機能です。システムPythonへ直接パッケージを入れると、OSのツールや他のアプリケーションとバージョンが競合する場合がありますが、仮想環境なら各プロジェクトに必要なバージョンを独立して管理できます。

この記事ではLinux、macOS、Windowsでの作成と確認から、requirements.txt、閉域環境のwheelhouse、systemd、安全な削除、トラブル対応まで説明します。コピーする前にPythonのバージョンとプロジェクトパスを実環境へ合わせてください。

Python venv:1つのベースPythonと、分離されたプロジェクトごとのパッケージ環境
1つのベースPython上で、プロジェクトごとにパッケージのインストール先を分離します

クイックスタート

プロジェクト内に.venvを作り、そのPythonでpipを実行するのが基本です。pipだけを呼ぶよりpython -m pipを使う方が、選択中のインタープリターとpipの対応を明確にできます。

mkdir -p ~/projects/sample-app
cd ~/projects/sample-app

python3 --version
python3 -m venv .venv
source .venv/bin/activate

python -m pip --version
python -m pip install --upgrade pip
python -m pip install requests
python -c "import requests; print(requests.__version__)"

deactivate

仮想環境ディレクトリはソースコードではありません。.venv/をGitへコミットせず、依存関係ファイルからいつでも再作成できるように管理します。

venvとは何か、何を分離するのか

Pythonの完全な複製ではなく、独立した実行環境

作成先にはpyvenv.cfg、実行ファイル用ディレクトリ、独立したsite-packagesが作られます。プラットフォームと作成オプションにより、Python実行ファイルはコピーまたはシンボリックリンクになります。venvはコンテナのようにOSを隔離する技術ではなく、作成に使ったベースPythonとOSライブラリへ依存します。

python3 -m venv .venv

find .venv -maxdepth 2 -type f -o -type l | sort | head -30
cat .venv/pyvenv.cfg

仮想環境で実行しているか正確に確認する

有効化スクリプトは、環境の実行ファイルディレクトリをPATHの先頭へ追加します。ただし有効化は必須ではないため、VIRTUAL_ENVだけで判定すると見落とす場合があります。Python内部でsys.prefixsys.base_prefixを比較する方が確実です。

python - <<'PY'
import sys

print("executable   :", sys.executable)
print("prefix       :", sys.prefix)
print("base_prefix  :", sys.base_prefix)
print("inside venv  :", sys.prefix != sys.base_prefix)
PY

作成前の確認

使用するPythonの実際の場所とバージョン、venvモジュール、pipのブートストラップ可否を確認します。複数Pythonがある場合は、python3.11のように対象を明示して作成してください。

command -v python3
python3 --version
python3 -m venv --help >/dev/null
python3 -m ensurepip --version

一部のLinuxではvenvやpipが別パッケージです。名称は配布元とPythonバージョンで異なるため、リポジトリで確認してから導入します。システムPythonでsudo pip installを使うことは避ける方が安全です。

# Debian/Ubuntu系の一般的な例
sudo apt update
sudo apt install python3-venv python3-pip

# RHEL/Rocky系では先に提供パッケージを確認
sudo dnf list --available 'python3*' | grep -E 'pip|virtualenv'

OS・シェル別の作成と有効化

環境作成有効化
Linux/macOS bash・zshpython3 -m venv .venvsource .venv/bin/activate
Linux/macOS fishpython3 -m venv .venvsource .venv/bin/activate.fish
Windows cmdpy -m venv .venv.venv\Scripts\activate.bat
Windows PowerShellpy -m venv .venv.venv\Scripts\Activate.ps1

有効化後はパスとバージョンを確認します。プロンプトの(.venv)は補助表示にすぎません。実インタープリターのパスも確認することで、別環境へインストールする誤りを減らせます。

command -v python
python --version
python -m pip --version
python -c "import sys; print(sys.executable)"

有効化せずに実行する

venvを使うためにsourceは必須ではありません。cron、systemd、CIでは有効化スクリプトへ依存せず、環境内Pythonの絶対パスを直接実行する方が動作を予測しやすく、ログ分析も容易です。

# Linux/macOS
/opt/sample-app/.venv/bin/python /opt/sample-app/app.py
/opt/sample-app/.venv/bin/python -m pip list

# Windows PowerShell
.\.venv\Scripts\python.exe .\app.py

パッケージとrequirements.txtを管理する

現在のPythonからpipを呼ぶ

python -m pip install --upgrade pip
python -m pip install 'requests>=2.32,<3'
python -m pip list
python -m pip check

pip checkは、インストール済みパッケージが宣言する依存関係の互換性を検査します。導入後にアプリケーションのテストと一緒に実行すると、不足や競合を早く発見できます。

環境のスナップショットを作成・再現する

pip freezeは直接・間接の依存パッケージの現在のバージョンを出力し、本番環境の記録に役立ちます。ただしOS、CPU、Pythonが変わると同じファイルで導入できない場合があるため、実行条件も記録してください。

python -m pip freeze > requirements.txt
python -m pip check

# 新しい環境で再現
python3 -m venv .venv-new
.venv-new/bin/python -m pip install --upgrade pip
.venv-new/bin/python -m pip install -r requirements.txt
.venv-new/bin/python -m pip check

プロジェクトへ含めるファイル

# .gitignore
.venv/
__pycache__/
*.py[cod]
.env

# バージョンとインストール状態を記録
python --version
python -m pip --version
python -m pip freeze

閉域・オフライン環境で運用する

ダウンロードするオンラインサーバーは、対象と同じOS、CPUアーキテクチャ、Pythonのメジャー・マイナーバージョンにそろえることが重要です。wheelはプラットフォームやPython ABIに依存する場合があり、別のPCで取得したものをコピーするだけでは失敗することがあります。

オンラインサーバーでwheelhouseを準備する

python3 -m venv bundle-venv
bundle-venv/bin/python -m pip install --upgrade pip

# wheelだけを許可すると、オフラインサーバーでソースビルドが必要なパッケージを事前に検出できる。
bundle-venv/bin/python -m pip download   --only-binary=:all:   --dest wheelhouse   -r requirements.txt

sha256sum wheelhouse/* > SHA256SUMS
tar -czf python-wheelhouse.tar.gz wheelhouse requirements.txt SHA256SUMS
sha256sum python-wheelhouse.tar.gz > python-wheelhouse.tar.gz.sha256

オフラインサーバーで検証してから導入する

sha256sum -c python-wheelhouse.tar.gz.sha256
tar -xzf python-wheelhouse.tar.gz

sha256sum -c SHA256SUMS

python3 -m venv .venv
.venv/bin/python -m pip install   --no-index   --find-links=wheelhouse   -r requirements.txt
.venv/bin/python -m pip check

--only-binary=:all:で失敗するパッケージには、互換wheelがありません。その場合はオンラインのビルドサーバーで必要なコンパイラーと開発ヘッダーを使ってwheelを作成し、同一条件の試験サーバーに新しい環境を作ってインストールと実行を確認します。

systemdサービスから利用する

systemdは対話シェルではないため、source .venv/bin/activateは不要です。ExecStartへPythonの絶対パスを指定し、秘密情報はソースコードと分離した権限制限付きファイルで管理します。

# /etc/systemd/system/sample-app.service
[Unit]
Description=Sample Python application
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
User=sampleapp
Group=sampleapp
WorkingDirectory=/opt/sample-app
EnvironmentFile=/etc/sample-app/sample-app.env
ExecStart=/opt/sample-app/.venv/bin/python /opt/sample-app/app.py
Restart=on-failure
RestartSec=5
NoNewPrivileges=true
PrivateTmp=true

[Install]
WantedBy=multi-user.target
sudo systemd-analyze verify /etc/systemd/system/sample-app.service
sudo systemctl daemon-reload
sudo systemctl enable --now sample-app.service
sudo systemctl status sample-app.service --no-pager
sudo journalctl -u sample-app.service -n 100 --no-pager

移動せず再作成すべき理由

インストールされたスクリプトのshebangには、環境のPythonへの絶対パスが記録される場合があります。別の場所やサーバーへコピーすると壊れる可能性があるため、venv自体を配布成果物として扱いません。新しい場所で環境を作り、依存関係ファイルやwheelhouseから再インストールするのが公式の推奨方法です。

# 既存環境の実行条件と依存関係を記録
.venv/bin/python --version
.venv/bin/python -m pip freeze > requirements.txt

# 新しい場所で再作成
python3 -m venv /opt/sample-app/.venv
/opt/sample-app/.venv/bin/python -m pip install -r requirements.txt
/opt/sample-app/.venv/bin/python -m pip check

安全に削除する

削除はディレクトリを取り除く操作ですが、変数の誤りや空のパスによって別データを消すおそれがあります。絶対パスとpyvenv.cfgを確認し、稼働中のサービスが使っていないか調べてください。

# このブロックはサブシェルで実行するため、取り消しても現在のログインシェルは終了しません。
(
  set -eu
  VENV="$(realpath -e -- .venv)"
  test -d "$VENV" && test -f "$VENV/pyvenv.cfg" || {
    echo '가상환경 디렉터리가 아니므로 중단합니다.' >&2
    exit 1
  }
  case "$VENV" in /|"$HOME"|/opt|/usr|/var)
    echo '삭제할 수 없는 상위 경로입니다.' >&2; exit 1 ;;
  esac
  printf 'delete target: %s\n' "$VENV"
  grep -R --fixed-strings "$VENV" /etc/systemd/system /etc/cron* 2>/dev/null || true
  # 上記結果と稼働中のサービス・cronを確認してから回答します。
  read -r -p '이 경로만 삭제하려면 DELETE 입력: ' answer
  if [ "$answer" != DELETE ]; then
    echo '취소했습니다.'
    exit 0
  fi
  rm -rf -- "$VENV"
)

本番環境の交換時は旧ディレクトリをすぐ削除せず、新環境を別パスに作成・試験してからサービスを切り替えます。問題があれば旧パスへ戻せます。

よくある問題と対処

症状最初の確認対処方針
No module named venvOSのvenvパッケージ現在のPythonに合うvenvをOSリポジトリから導入
導入したのにimportできないsys.executablepython -m pip --version同じインタープリターのpipで再導入
PowerShellで有効化できない実行ポリシーと組織の方針独自に緩和せず、Pythonの絶対パスで実行するか管理者の指示に従う
コピーした環境が動かないshebangの絶対パス新しい場所で環境を再作成し、依存関係を再導入
オフラインwheelを導入できないOS・CPU・Python ABIタグ対象と同一条件でwheelhouseを再作成
pipの依存関係が競合python -m pip checkバージョン制約を整理し、新しい環境で検証
python -c "import sys; print(sys.executable); print(sys.version)"
python -m pip --version
python -m pip list
python -m pip check
python -m site

venv・virtualenv・pipx・condaの選択基準

  • venv:標準ライブラリだけでプロジェクト別環境を手動管理する場合に適する。
  • virtualenv:豊富な作成オプションや幅広いPython互換機能が必要な場合に検討する。
  • pipx:BlackやAnsible Lintなど、どこからでも実行するPython CLIをアプリケーション別環境へ導入する場合に適する。
  • conda:Pythonパッケージとネイティブライブラリを一緒に管理する科学・データ分野で主に使う。

一般的なサーバー・開発環境の依存関係分離なら、まず標準のPython venvを使い、CLI配布やネイティブ依存など明確な要件がある場合に他のツールを選ぶと単純です。

実務チェックリスト

  1. 対象Pythonの実行ファイルとバージョンを確認してから作成する。
  2. python -m pipで導入し、pip checkで検証する。
  3. .venv/をバージョン管理から除外し、requirementsまたはlockファイルを保管する。
  4. 本番サービスは有効化スクリプトではなくPythonの絶対パスを使う。
  5. コピー・移動せず、対象の場所で再作成する。
  6. 閉域用バンドルは同じOS・CPU・Python条件で作り、SHA-256を検証する。
  7. 削除前に実パス、pyvenv.cfg、サービスとcronからの参照を確認する。

関連ガイド

公式資料

まとめ

venvの要点は有効化コマンド自体ではなく、使うインタープリターとパッケージパスを分離し、再現可能に管理することです。開発中は.venvを有効化し、運用自動化では絶対パスを指定します。依存関係ファイル、実行条件、完全性検証、交換手順を併せて管理すれば、サーバーや閉域環境でも安定して運用できます。