🙌

【Python】仮想環境(venv)の仕組みを動作の流れから理解する

に公開

はじめに

以前の記事で、仮想環境についての基本的な知識と、使用する理由についてまとめました。
(参考: https://qiita.com/mabo23/items/c2cb995a98d7003d7bdd)

この記事では、実際にPython標準の仮想環境作成モジュール「venv」使って仮想環境を構築する手順について、実際の動作をイメージしやすいよう、仕組みについて言及しながら解説していきます。

※ なお、この記事は仮想環境の基本と使用理由について押さえている方が対象です。もし、まだ理解できていないという方は、上記の記事を参考にしていただけますと幸いです。

※ また、「シェルとプロセスの関係」について押さえておくことでより正しく処理の流れを理解することができます。シェルとプロセスの関係について、以下の記事にまとめていますので、よろしければ参考にしてみてください。
(参考: https://qiita.com/mabo23/items/45b4838050a95903d10e)

※ 本記事では、Mac や Linux など Unix 系システムでの動作を前提としています。
Windows ユーザの方は、PowerShell や .bat ファイルを使った activate 方法が異なるため、適宜読み替えてください。

本記事で理解しておきたいポイント

  • 仮想環境の基本概念と必要性
  • venv を使った仮想環境の作成と有効化・無効化の手順
  • PATH などの環境変数が果たす役割
  • fork → exec によるプロセス実行の流れ
  • source などのビルトインコマンドと外部コマンドの違い

仮想環境について簡単におさらい

仮想環境とは、あるプロジェクト専用のPython実行環境を、自分のPCの中に一時的に用意する仕組みのことです。これを使うことで、複数のプロジェクトごとに異なるライブラリやバージョンのPythonを共存させることができます。

Image 2025-07-22 at 13.07.jpeg
https://www.tutorialspoint.com/python/python_virtual_environment.htm より画像引用

Pythonでは、外部ライブラリの多くを pip install によってインストールして使用します。
もし仮想環境を使わず、グローバル環境(OS全体で共通のPython)に直接インストールしてしまうと、他のプロジェクトとライブラリのバージョンが衝突してしまい、動かなくなってしまうことがあります。

例えば、あるプロジェクトでは Django 3.2 が必要で、別のプロジェクトでは Django 4.0 が必要だとしましょう。これを同時にグローバル環境に共存させることはできません。
しかし、仮想環境を使えば、各プロジェクトごとに別々のDjangoを自由にインストールでき、互いに干渉しないようにできます。

このように仮想環境は、プロジェクトごとの依存関係をきちんと分離するための土台となる非常に重要な仕組みです。

仮想環境の作成手順

  1. ディレクトリを作る
    $ mkdir myapp
    $ cd myapp

  2. 仮想環境を作る(最初の1回だけ)
    $ python3 -m venv venv

  3. 仮想環境を有効化(毎回の作業時)
    $ source venv/bin/activate

  4. プログラムを書く・pip installする

  5. 必要に応じて作業が終わったら無効化
    $ deactivate

1. ディレクトリを作る

まずは、ターミナルやコマンドプロンプトで、仮想環境を置きたいディレクトリに移動しましょう。
プロジェクト用のフォルダがまだない場合は、作成しておくとわかりやすいです。

$ mkdir project  # ディレクトリの作成
$ cd project     # 当該ディレクトリに移動

2. venvによる仮想環境の作成

Python 3.3以降には、標準ライブラリとして venv モジュールが搭載されており、追加のツールを入れずに仮想環境を簡単に作成することができます。

仮想環境を作成するコマンド例
python3 -m venv venv  # 仮想環境 venv の作成

各コマンドの意味

  • python3: Pythonインタプリタを呼び出す
    ※「インストールされている Python 3.x の実行環境を起動する」という意味

  • -m: Python モジュールをスクリプトとして実行するためのオプション
    例えば python3 -m venv は「venv というモジュールの中にある処理を実行せよ」という意味になります。

  • venv(1つ目): 使用するモジュール名
    venv.py という Python ファイル(もしくはパッケージ)がモジュールです。

  • venv(2つ目): 作成するディレクトリ名
    ここで指定された名前のディレクトリに、仮想環境の構成(Python実行ファイル・ライブラリのコピー・activateスクリプトなど)が生成されます。
    ここでは任意のディレクトリ名をつけることができます。

このコマンドによって、venv という名前のフォルダが作られ、その中にPythonの実行ファイルやパッケージ管理に必要な仕組み一式が構成されます。macOSやLinuxでは bin/ ディレクトリが作られ、その中に pythonpip などの実行ファイルが配置されます。

仮想環境 venv/ ディレクトリ構成(例)

(例)venv ディクレトリ構成
venv/
├── bin/                    # 仮想環境を操作するための実行ファイルやスクリプトがを格納
│   ├── activate            # 仮想環境を有効化するためのシェルスクリプト
│   ├── activate.csh
│   ├── activate.fish
│   ├── pip
│   ├── pip3                # 仮想環境専用のpipコマンド
│   ├── python         
│   └── python3             # 仮想環境専用のPython実行ファイル
├── include/                # Python C拡張をビルドするときに使うCヘッダファイルのためのディレクトリ
├── lib/                    # 仮想環境が使う Python標準ライブラリや追加ライブラリ(site-packages) を保存する場所
│   └── python3.X/
│       └── site-packages/  # pip install したライブラリの保存先
└── pyvenv.cfg              # 仮想環境の設定ファイル

この仮想環境は、実際にはグローバルにインストールされているPythonの実行ファイルをコピーまたはリンクする形で作られますが、内部的に仮想環境用に分離されたライブラリの検索パス(site-packages)を使うようになっています。

3. 仮想環境の有効化

仮想環境を作成しただけでは、まだその環境は有効になっていません。仮想環境を使って開発を始めるには、まずその環境を「有効化(activate)」する必要があります。

仮想環境を有効化するため、以下のコマンドをターミナルで実行します。

仮想環境を有効化するコマンド
$ source venv/bin/activate

このコマンドを実行することにより、現在のシェルプロセスに仮想環境が反映されるようになります。

※ Bash などの一部のシェルでは、source.(ドット)と同義です
したがって、以下のコマンドも有効です。

仮想環境を有効化するコマンド(bashなど一部のシェル)
$ . venv/bin/activate

有効化に成功すると、プロンプトの先頭に (venv) のような表示が付きます。
これは、現在のシェルセッションが仮想環境に切り替わっていることを意味します。

この状態で python3 と入力すると、仮想環境内の Python 実行ファイルが使われます。同様に pip3 を使えば、インストールされるパッケージはすべてこの仮想環境専用の領域(venv/lib/.../site-packages)に保存されるようになります。
つまり、この状態ではグローバル環境を一切汚さずにライブラリを自由に追加・削除することが可能になるわけです。

(例)venv ディクレトリ構成
# 一部省略

venv/
├── bin/                    # 仮想環境を操作するための実行ファイルやスクリプトがを格納
│   ├── activate            # 仮想環境を有効化するためのシェルスクリプト
│   ├── pip3                # 仮想環境専用のpipコマンド       
│   └── python3             # 仮想環境専用のPython実行ファイル
├── lib/                    
│   └── python3.X/
│       └── site-packages/  # pip install したライブラリの保存先

さらに、この動作を理解するためには、
① そもそもsourceコマンドが何か
② なぜこのコマンドを実行することで仮想環境が有効になるのか
を知る必要があります。

3-1. source コマンド

source コマンドは、主にシェルスクリプトや設定ファイルを現在のシェル環境で読み込んで実行するためのコマンドです。

基本構文
$ source ファイル名 or ファイルパス

通常、スクリプトを実行すると、新しいシェルプロセスが始まり、その中で処理がされます。

通常のスクリプト実行

Scan Jul 25, 2025 at 17.01 3.jpeg
※ 筆者の手書きメモ

sourceコマンドを使用することで「現在のシェル」内でファイルの読み込み・実行を行ないます。
sourceコマンドはビルトインコマンドで、新たなプロセスで実行されるわけではないので、注意しましょう

ビルトインコマンド(source)による実行

Scan Jul 25, 2025 at 18.jpeg
※ 筆者の手書きメモ

なお、ビルトインコマンドと外部コマンド(バイナリファイル・スクリプトファイル)については、よろしければ以下の記事をご参照ください。
(参考: https://qiita.com/mabo23/items/8bf73985946c541572c4)

ここで、仮想環境を有効化するためのコマンドをもう一度見てみましょう。

仮想環境を有効化するコマンド
$ source venv/bin/activate

これは、先ほど紹介した venv ディレクトリ構成例を元に一部抜粋すると、以下のようになります。

venv ディクレトリ構成の一部抜粋
venv/
├── bin/                    # 仮想環境を操作するための実行ファイルやスクリプトがを格納
│   ├── activate            # 仮想環境を有効化するためのシェルスクリプト
.   .
.   .
.   .

つまり、venv フォルダの中にある activate ファイル(シェルスクリプト)を現在のシェルプロセスに読み込んでいます。
これによって、activate ファイルに記述されたシェルスクリプトが現在のプロセスに反映されます。

ちなみに、この activate ファイルは、venv モジュールを使って仮想環境を作成するときに自動的に作成されるシェルスクリプトファイルです。

そのため、$ source venv/bin/activateによってスクリプトファイルが実行されます。

3-2. なぜ activate で仮想環境になるのか = 環境変数の仕組み

activate は普通のシェルスクリプトファイルです。通常のシェルスクリプト同様、sourceコマンドを実行することで、スクリプトファイルの内容を現在のシェルプロセスに反映されます。

この activate というスクリプトファイルを実行することで、PATHという環境変数に変化があります。
PATHの先頭に venv/bin が置かれるということが環境変数内部で行われます。

具体的には以下のような処理が行われます。

3-2-1. PATH の変更

PATH 環境変数の先頭に、仮想環境内の bin/ ディレクトリが追加されます。
これにより、同名のコマンド(例えば python3pip3のような bin/ ディレクトリは以下のディレクトリ)が仮想環境内のものを優先的に使うようになります。

例(bashやzshの activate スクリプトより)
_OLD_VIRTUAL_PATH="$PATH"
VIRTUAL_ENV="/home/user/project/venv"
PATH="$VIRTUAL_ENV/bin:$PATH"
export PATH

新たなPATH変数は以下の順番でディレクトリを探索することになります。

PATH変更前・変更後
# PATH変更前
/usr/local/bin:/usr/bin:/bin:...

# PATH変更後
/home/user/project/venv/bin:/usr/local/bin:/usr/bin:/bin:...

これにより、以後の python3pip3 コマンドは、グローバル環境の /usr/bin/python3 ではなく、venv/bin/python3 を指すようになります。

3-2-2. VIRTUAL_ENV 環境変数の定義

現在どの仮想環境が有効になっているかを示すため VIRTUAL_ENV という環境変数が設定されます。
この変数は deactivate するときにも使われます。

VIRTUAL_ENVの定義
VIRTUAL_ENV="/home/user/project/venv"
export VIRTUAL_ENV

3-2-3. シェルプロンプトの変更(任意)

仮想環境が有効であることを視覚的にわかりやすくするため、プロンプト(PS1)に仮想環境の名前が追加されます。

(例)venv $ のような表示
PS1="(`basename \"$VIRTUAL_ENV\"`) $PS1"

3-2-4. deactivate 関数の定義

仮想環境を終了させるための関数 deactivate がシェルに追加されます。
この関数が呼び出されると、PATH や PS1 の変更が元に戻り、仮想環境が無効になります。

deactivate 関数の定義
deactivate () {
    # 元の PATH を復元
    PATH="$_OLD_VIRTUAL_PATH"
    export PATH
    # プロンプトを戻す(あれば)
    PS1="$_OLD_VIRTUAL_PS1"
    export PS1
    # その他のクリーンアップ
    unset VIRTUAL_ENV
    unset deactivate
}

これらの一連の処理によって、activate ファイルが読み込まれ、仮想環境が有効化します。

4. 仮想環境内で作業

仮想環境を有効化し、python3 スクリプトファイル を実行すると、PATH の設定により仮想環境内の python3 実行ファイル(Pythonインタプリタ)が使用され、それが新たなプロセスとしてメモリにロードされ、スクリプトを実行していきます。

Scan Jul 26, 2025 at 12.49.jpeg
※ 筆者の手書きメモ

仮想環境を有効化すると、PATH の先頭に仮想環境の bin/ ディレクトリが追加されるため、
python3 コマンドを打ったときに 仮想環境内の python3 実行ファイル(実体はシンボリックリンクや実行ファイル)を使うようになります。

そして、python3 スクリプトファイル.py を実行すると、

  • その仮想環境の python3 実行ファイル がプロセスとして起動され、
  • 指定されたスクリプトファイルを読み込み、
  • Pythonインタプリタがそのスクリプトを解釈・実行します
(例)venv ディクレトリ構成
venv/
├── bin/                    
│   ├── activate            
│   ├── pip3                
│   └── python3             # 仮想環境専用のPython実行ファイル(Pythonインタプリタ)
├── lib/                    
│   └── python3.X/
│       └── site-packages/  
└── pyvenv.cfg              

このときにロードされる Python 実行ファイルは、システム全体ではなく仮想環境用にインストールされたものです。

また、仮想環境を有効化している間に外部かインストールしたパッケージ(ファイル)は lib/ 配下の site-packages/ に保存されます。

5. deactivate

deactivate は仮想環境を使わない状態に戻すための処理です。

現在使用している仮想環境を修了するために以下のコマンドを実行します。

deactivate
$ deactivate

これにより、仮想環境は消えないが使わない状態にすることができます。

deactivate 前・後
# deactivate 前
/home/user/project/venv/bin:/usr/local/bin:/usr/bin:/bin:...

# deactivate 後
/usr/local/bin:/usr/bin:/bin:...

仮想環境そのものはディレクトリとして残っているため、次回以降も同じように
$ source venv/bin/activate を実行することで再び利用できます。

まとめ

  • ストレージ上:venv/ フォルダ群として存在する
  • シェル環境上:PATH を変更することで仮想環境を「使う」状態にする
  • メモリ上:python を実行したときに、仮想環境の子プロセスがメモリに展開される

この仕組みを理解すると、仮想環境はプロセスの中に埋め込まれているものではなく、ストレージ上の構成とシェル環境変数の操作で成り立っていることがわかります。

また、仮想環境を有効にしている間も、プロセスの実行そのものは常に「fork→exec」の原則に従って行われていることがわかります。

Python仮想環境の操作は、一見単純に見えますが、実際にはOSとシェル、ファイルシステム、プロセス、環境変数といった複数の概念が密接に連動しています。
仮想環境を深く理解するには、単に venv フォルダがあるだけでなく、「どうやってその実行環境がメモリ上に展開されるのか」という視点を持つことが大切です。

本記事で紹介した「venv」を使った仮想環境の作成と運用の流れを、自分の手元のプロジェクトでぜひ実践してみてください。

最後までお読みいただき、ありがとうございました。

参考・画像引用元URL

https://docs.python.org/ja/3.13/library/venv.html

https://qiita.com/shun_sakamoto/items/7944d0ac4d30edf91fde

https://www.insource.co.jp/python-gakuin/mail-backnumber/vol30.html

https://qiita.com/mabo23/items/c2cb995a98d7003d7bdd

https://qiita.com/mabo23/items/c2cb995a98d7003d7bdd

https://qiita.com/mabo23/items/45b4838050a95903d10e

※ ディレクトリ構成の例はChatGPTより引用

Discussion