当サイトの一部ページには、アフィリエイト・アドセンス・アソシエイト・プロモーション広告を掲載しています。

Amazonのアソシエイトとして、Security Akademeiaは適格販売により収入を得ています。

広告配信等の詳細については、プライバシーポリシーページに掲載しています。

消費者庁が、2023年10月1日から施行する景品表示法の規制対象(通称:ステマ規制)にならないよう、配慮して記事を作成しています。もし問題の表現がありましたら、問い合わせページよりご連絡ください。

参考:令和5年10月1日からステルスマーケティングは景品表示法違反となります。 | 消費者庁

WSL2とvenvで分離するPython開発・実験環境設計【Windows編】

この記事は「既存WSLとは独立した新規WSL(Ubuntu)を作る」手順の続きとして、WSL上でPython実験環境を安全・再現可能に保つための設計指針をまとめたものです。
最後に、venv仮想環境でサンプルPythonプログラムを実行するところまで到達します。
この手順を見れば、venvでどうPythonを実行すればよいかが分かるように構成しています。

ゴール(今回の構成で得たい性質)

本記事で構築する環境のゴールは、単にPythonを動かすことではありません。実験・検証・失敗を前提にしたときに「安全に戻れる」状態を作ることです。

WSL上で、次の性質を満たすことを目標とします。

  • OS(WSLディストリー)を汚しにくい
    依存関係の実験を繰り返しても、Ubuntu全体やWindows本体が破綻しにくい
  • 壊れたら即復旧できる
    最悪"venv/"ディレクトリーを削除するだけでPython環境を初期状態に戻せる
  • 再現性が高い
    READMEに手順を書けば、他人も同じ環境を再現できる
  • セキュリティ的に安全側
    危険な実験(LLM連携、外部入力処理など)でも、被害範囲を限定できる

これらはすべて、実験用の環境として非常に重要な要件です。

推奨の「二重サンドボックス」構成

今回採用する構成は、次の三層構造です。

Windows(ホストOS)
 └─ WSL2(実験専用Ubuntu、名前は任意)
     └─ Python venv(プロジェクト単位)

「Windowsの中に、実験用Linuxを1台増設している。そして、そのLinuxの中でさらにPython環境を分離している」という構造です。つまり、サンドボックスは二重になっています。

手順だけを見ると複雑に見えるかもしれませんが、構造としては役割を分けて重ねているだけです。

この構成をどうイメージすればよいか

まずは、それぞれの層を次のように捉えると理解しやすくなります。

  • Windows(ホストOS)
    普段使っている環境。ここは絶対に壊したくない「安全地帯」
  • WSL2(Ubuntu)
    Windowsの中に新しく作った、実験専用のLinuxマシン
  • Python venv
    そのLinuxの中に作る、プロジェクト専用のPython実験環境

なぜ「二重」(+1)にするのか

この構成では、壊れやすいものほど内側に閉じ込めています。

  • Windows
    → 日常環境。Python実験の影響を一切受けない
  • WSL(Ubuntu)
    → 危険になりうる実験をまとめて隔離する「箱」
  • venv
    → Python依存関係の試行錯誤を受け止める最内層

そのため、以下のように段階的な復旧が可能になります。

  • Pythonライブラリが壊れても ⇒ “venv/"ディレクトリーを削除
  • Ubuntu環境自体を壊しても ⇒ WSLディストリーを削除
  • Windows本体は ⇒ 影響なし

WSLを使わない選択肢

本記事ではWSL+venvを採用していますが、選択肢はこれに限りません。

macOSやLinuxのネイティブ環境、Dockerコンテナー、あるいは仮想マシン(VM)など、目的に応じた構成が考えられます。

例えば、今回の構成の一部を以下のように変化できます。

  • macOSやLinuxの場合
    → ホストOS+venv
  • Docker
    → コンテナー+(必要に応じて)venv

「慣れている環境は」「何を理解したいか」「どこまで隔離・再現したいか」によって環境を選んでください。
私のメイン環境がWindowsであり、WSLのほうが簡単に構築できそうでしたので、本記事の構成を採用しました。

WSL上でのPython / venv設計指針

指針A:作業場所は"/home"ディレクトリー配下(Linux側)に固定する

WSLでは Windowsドライブが"/mnt/c"や"/mnt/d"のように見えます。便利ですが、ここをカレントディレクトリーして、Pythonの仮想環境作成(venv)や依存管理する行為は地雷になりがちです。

  • 避けたい場所:"/mnt/c"や"/mnt/d"
    • Windowsのファイルシステム=drvfs
  • 推奨の場所:ユーザーのホームディレクトリー("/home/<user>"ディレクトリー)配下
    • Linuxのext4側

“/mnt/d/"ディレクトリー配下で「python3 -m venv venv」コマンドを実行すると、ensurepipが失敗してvenvが壊れることがあります。さらに、venvにpython はあるのにpipがないなど、中途半端な環境ができあがりやすいといえます。

よって、WSLでvenvを使うなら、"/home/<user>"ディレクトリー配下に固定が安全です。

指針B:activateに頼らず「venv/bin/python」を明示する

venv環境ではPythonを使う際に、以下の2つのアプローチがあります。

  • ①source venv/bin/activateコマンドで有効化して pythonを打つ
  • ②venv/bin/pythonコマンドを毎回明示して実行する

実験・検証用途では②を推奨します。

  • 「どのPythonが動いているか」が常に明確
  • 端末を閉じたり、別セッションに切り替えたりしてもブレない
  • READMEに貼ったコマンドが、そのまま再現手順になる
ipusiron@MHL:~/mcp-sandbox$ ~/mcp-sandbox/venv/bin/python 1-1-server.py

※ユーザー名はipusiron、ホストOS名はMHLです。"mcp-sandbox"は実験用ディレクトリーです。

指針C:Ubuntuではpython3-venvとpython3-pipをOS側に入れておく

Ubuntu系では、python3が入っていてもvenvが作れないことがあります。

たとえば、"ensurepip is not available"エラーが出ると、「venvを作成できたがpipが入っていない」という症状が出ます。

そのため、まずOS側(ここでは今回はUbuntu)に次のコマンドでpython3-venvとpython3-pipを入れておくのが定石です。

ipusiron@MHL:~$ sudo apt update
ipusiron@MHL:~$ sudo apt install -y python3 python3-venv python3-pip
  • python3-venv:python3 -m venvのため
  • python3-pip:pip周りの不整合を減らす(venv内pip構築が安定する)

指針D:venvは「直す」より「捨てて作り直す」

venvを利用しているのであれば、壊れたら修理より、「削除→再作成」が最短で安全です。

ipusiron@MHL:~/mcp-sandbox$ rm -rf venv
ipusiron@MHL:~/mcp-sandbox$ python3 -m venv ~/mcp-sandbox/venv
ipusiron@MHL:~/mcp-sandbox$ ~/mcp-sandbox/venv/bin/python --version ←念のためにバージョン確認
Python 3.10.12
ipusiron@MHL:~/mcp-sandbox$ ~/mcp-sandbox/venv/bin/pip --version ←念のためにバージョン確認
pip 22.0.2 from /home/ipusiron/mcp-sandbox/venv/lib/python3.10/site-packages/pip (python 3.10)

指針E:依存はrequirements.txt / pyproject.tomlに寄せる

実験が進むとpip installを何度も実行することになります。「何を入れたか」が消えると再現性が落ちます。

  • 小規模:requirements.txt
  • しっかり管理:pyproject.toml(Poetry等でも可)

まずは以下のコマンドを実行して、venvに今入っているPythonパッケージと、その正確なバージョン一覧を"requirements.txt"ファイルに書き出せば十分でしょう。

$ ./venv/bin/pip freeze > requirements.txt

“/home/ipusiron/mcp-sandbox/requirements.txt"ファイルが出力されます。

“requirements.txt"ファイルがあれば、別環境でも次のコマンドを実行するだけです。「同じパッケージ」かつ「同じバージョン」かつ「同じ依存関係」、すなわち(ほぼ)同一に再構築されます。

$ pip install -r requirements.txt

WSL(Ubuntu)上でvenvを作ってPythonサンプルを実行するまで【実践編】

全体の流れ(概要)

  1. WSL2が使えることを確認
  2. Ubuntuのrootfs(完成済みLinux)をダウンロード
  3. wsl –importコマンドで新しいWSLを作成
  4. 起動してrootで入る
  5. 一般ユーザーを作成し、sudo権限を付与
  6. 一般ユーザーで入り直す
  7. venvを導入する
  8. venv環境を構築する
  9. venv環境下でPythonプログラムを実行する

以下、すべてPowerShell+WSL上で実行します。

① WSL2が使えることを確認する

「WSL自体が入っているか」「WSL2が使える状態か」を確認します。

PS C:\Users\owner> wsl --version

「バージョン2.x.x」と出力されなければ、WSL2は使えません。WSL2が使えない場合は、以降の手順を進めても意味がありません。

② Ubuntu のrootfsをダウンロードする

rootfs(root filesystem)とは、ISOやインストーラではなく、すでに展開済みのLinux の完成形です。"/bin"、"/etc"、"/usr" などが最初から入っています。

PS C:\Users\owner> D:
PS D:> mkdir wsl ←作業ディレクトリーを作っている。
PS D:> cd wsl
PS D:\wsl> curl.exe -L -o ubuntu-wsl.rootfs.tar.gz `
https://cloud-images.ubuntu.com/wsl/releases/22.04/current/ubuntu-jammy-wsl-amd64-wsl.rootfs.tar.gz
  • curl.exe:PowerShellのcurlエイリアスではなく、本物のcurlを使う
  • -L:リダイレクトを追跡する。これがないと286バイトのダミーファイルを掴む。
  • -o ubuntu-wsl.rootfs.tar.gz:保存するファイル名を指定

ダウンロード後にlsコマンドでファイル容量をチェックしてください。

サイズが数百バイト(286バイトなど)の場合は失敗です。正常なら200Mバイト以上になります。

PS D:\wsl> ls

    ディレクトリ: D:\wsl

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
-a----        2026/01/23     21:58      234074612 ubuntu-wsl.rootfs.tar.gz

③ 新規WSLとしてimportする

WSLディストリの実体が置かれる場所を用意します。

PS D:\wsl> mkir mcp-ubuntu

自分の実験に合った名前にしましょう。

既存WSLを確認します。

PS D:\wsl> wsl -l -v
  NAME              STATE           VERSION
* Ubuntu-20.04      Stopped         2
  kali-linux        Stopped         2
  Ubuntu            Stopped         2
  docker-desktop    Stopped         2

次のコマンドで新規WSLとしてインポートします。

PS D:\wsl> wsl --import mcp-ubuntu D:\wsl\mcp-ubuntu D:\wsl\ubuntu-wsl.rootfs.tar.gz --version 2
  • –import:新しいWSLディストリを作成する
  • mcp-ubuntu:WSLの名前(自由に決められる)
  • D:\wsl\mcp-ubuntu:Linuxファイルシステムの実体が置かれる場所
  • ubuntu-wsl.rootfs.tar.gz:使用するrootfs
  • –version 2:WSL2として作成する(必須)

登録を確認します。

PS D:\wsl> wsl -l -v
  NAME              STATE           VERSION
* Ubuntu-20.04      Stopped         2
  kali-linux        Stopped         2
  mcp-ubuntu        Stopped         2 ←追加された。
  Ubuntu            Stopped         2
  docker-desktop    Stopped         2

④ rootで起動する

rootfsには一般ユーザーが存在しないので、まずrootで起動します。

PS D:\wsl> wsl -d mcp-ubuntu ←WSL(Ubuntu)を起動。
root@MHL:/mnt/d/wsl# ←ルート権限のプロンプトが出る。

カレントディレクトリー"/mnt/d/wsl"はWindowsのファイルシステムなので要注意です。
ファイル作成や実験する際には、場所を変えます。

⑤ 一般ユーザーを作成し、sudo権限を付与する

root@MHL:/mnt/d/wsl# adduser ipusiron
(パスワードを設定、その他はそのままでOK)

useraddコマンドではなくadduserコマンドを使うのは、対話的で安全だからです。

今追加した一般ユーザーをsudoグループに属させます。結果的にsudo権限を付与したことになります。

root@MHL:/mnt/d/wsl# usermod -aG sudo ipusiron
  • usermod:ユーザー設定変更
  • -G sudo:sudoグループに追加
  • -a:"append"のこと。グループを追加、すわなち既存グループを保持ということ。
    • このオプションを忘れると事故る。追加ではなく上書きになってしまう。結果的に自分自身のグループ(ipusiron)やその他・追加されていた補助グループが消えてしまう。

⑥ 一般ユーザーで入り直す

root@MHL:/# exit ←rootユーザーをログアウト。
PS D:\wsl> wsl -d mcp-ubuntu -u ipusiron ←ユーザー名を指定してWSL(Ubuntu)を起動。
ipusiron@MHL:/mnt/d/wsl$ whoami
ipusiron
ipusiron@MHL:/mnt/d/wsl$ id
uid=1000(ipusiron) gid=1000(ipusiron) groups=1000(ipusiron),27(sudo) ←sudoグループに属する。

これでrootではない安全な作業環境になります。

⑦ venvを導入する

ipusiron@MHL:/mnt/d/wsl$ cd
ipusiron@MHL:~$ sudo apt update
ipusiron@MHL:~$ sudo apt install -y python3 python3-venv python3-pip

⑧ venv環境を構築する(プロジェクト専用Pythonを作る)

実験用ディレクトリーを作成し、移動します。

ipusiron@MHL:~$ mkdir -p mcp-sandbox
ipusiron@MHL:~$ cd mcp-sandbox/

venvを作成します。

ipusiron@MHL:~/mcp-sandbox$ python3 -m venv ~/mcp-sandbox/venv
Python 3.10.12

成功したら、venv環境下のPythonとpipの存在、そのバージョンを確認します。

ipusiron@MHL:~/mcp-sandbox$ ~/mcp-sandbox/venv/bin/python --version
Python 3.10.12
ipusiron@MHL:~/mcp-sandbox$ ~/mcp-sandbox/venv/bin/pip --version
pip 22.0.2 from /home/ipusiron/mcp-sandbox/venv/lib/python3.10/site-packages/pip (python 3.10)

⑨ venv環境下でPythonプログラムを実行する

最後に、実際にvenvのPythonでプログラムを実行してみます。

サンプルプログラムを作成します。

ipusiron@MHL:~/mcp-sandbox$ cat > hello_venv.py << 'EOF'
import sys
import platform

print("Hello from WSL + venv")
print("Python executable:", sys.executable)
print("Python version   :", sys.version.split()[0])
print("Platform         :", platform.platform())
EOF
ipusiron@MHL:~/mcp-sandbox$ ls hello_venv.py
hello_venv.py

venvのPythonで実行してみます。

ipusiron@MHL:~/mcp-sandbox$ ./venv/bin/python hello_venv.py
Hello from WSL + venv
Python executable: /home/ipusiron/mcp-sandbox/venv/bin/python
Python version   : 3.10.12
Platform         : Linux-5.15.133.1-microsoft-standard-WSL2-x86_64-with-glibc2.35

補足ですが、venvの外側にプログラムファイルは存在します。

以下はその例を示すディレクトリー構造になります。

project/
├─ venv/          ← Python実行環境(使い捨て・生成物)
├─ hello_venv.py  ← アプリケーションコード(人間が書くもの)
├─ server.py
└─ requirements.txt

Python公式ドキュメントでも、venvは次のように扱われます。
・プロジェクト直下に".venv/"や"venv/"を配置
・アプリケーションコードはその外側
・実行時に環境を切り替える
今回の構成は、Pythonの設計思想に沿った、ごく自然な使い方となっています。

【補足】Colabとの違いについて

Google Colaboratory(Colab)は、Pythonコードをすぐに試せる便利な環境ですが、本記事で扱っているWSL+venv構成とは目的が異なります。

Colabは一時的な実行環境であり、OSレベルの挙動や標準入力・標準出力を使ったプロセス実験、環境の継続的な管理・再現には向いていません。

一方、本記事の構成は、Linux環境そのものを把握しながら、安全に実験・検証を行うことを目的としています。

用途に応じて、ColabとWSLを使い分けるのが現実的です。