1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Macで研究開発環境をゼロから構築する完全ガイド(第4回)

1
Posted at

第4回 Python仮想環境(venv)を仕組みから理解する 〜なぜ仮想環境が必要なのか〜

対象読者

  • Homebrew版Pythonを導入した方
  • Pythonの仮想環境(venv)を初めて使う方
  • python3 -m venv .venv の意味を理解したい方
  • 研究や開発でPython環境を整理したい方

AI利用について

✍️ 本記事は 生成AI(ChatGPT)によって作成 されました。
誤りがあればコメント等でご指摘いただけると助かります。

なお、本記事に含まれる内容については、執筆時点での情報に基づいています。
環境やソフトウェアのバージョンによって挙動が異なる場合があるため、必要に応じて公式ドキュメントもあわせて参照してください。

はじめに

前回は、Homebrew版Pythonを導入し、Apple標準Pythonとの違いや、PATHの仕組みについて解説しました。

これでMac上で開発用のPythonを利用する準備は整いました。

しかし、ここで新たな問題が生まれます。

例えば、NumPyをインストールしたい場合、多くの人は次のように実行します。

python3 -m pip install numpy

もちろん、この方法でもNumPyはインストールできます。

しかし、このコマンドをそのまま使い続けると、Mac全体で利用するPython環境へNumPyが追加されることになります。

最初のうちは問題ありません。

しかし、研究や開発を続けていくと、複数のプロジェクトを同時に扱うようになります。

例えば、

  • 機械学習の勉強
  • 大学の課題
  • 趣味で作るツール

など、それぞれ異なるライブラリやバージョンを必要とすることがあります。

そのような状況で、すべてのプロジェクトが同じPython環境を共有してしまうと、ライブラリ同士が衝突し、思わぬトラブルの原因となります。

そこで登場するのが、

Python仮想環境(Virtual Environment)

です。

この記事では、単に仮想環境を作る方法を紹介するのではなく、

「仮想環境とは何か」「なぜ必要なのか」「内部で何が起きているのか」

という仕組みまで理解することを目標に解説していきます。

なぜ仮想環境が必要なのか

まずは、仮想環境が必要になる理由を考えてみましょう。

例えば、研究Aでは

NumPy 2.2

を利用しているとします。

一方で、研究Bでは古いプログラムとの互換性のために

NumPy 1.26

が必要だったとします。

もし両方とも同じPython環境を利用している場合、

Python
├── numpy 2.2
├── scipy
├── matplotlib

という状態から、

研究Bのために

python3 -m pip install numpy==1.26

を実行すると、

Python
├── numpy 1.26
├── scipy
├── matplotlib

となり、NumPyのバージョンが上書きされてしまいます。

すると、今度は研究Aが動かなくなる可能性があります。

つまり、

一つのPython環境を複数のプロジェクトで共有することには、大きなリスクがある

のです。

仮想環境という考え方

この問題を解決するために用意されているのが、Python仮想環境(venv)です。

仮想環境を利用すると、それぞれのプロジェクト専用のライブラリ環境を作ることができます。

イメージすると、次のようになります。

                 Homebrew版Python
                        │
        ────────────────┼────────────────
                        │
          ┌─────────────┴─────────────┐
          │                           │
      Project A                   Project B
          │                           │
        .venv                       .venv
          │                           │
   numpy 2.2                  numpy 1.26
   matplotlib                 scipy

ここで重要なのは、

Python本体は共有し、ライブラリだけをプロジェクトごとに分離している

という点です。

つまり、Pythonそのものを毎回コピーしているわけではありません。

Python本体はHomebrew版Pythonを利用しながら、

ライブラリだけをプロジェクトごとに独立して管理します。

これが、Python仮想環境の基本的な考え方です。

実際に仮想環境を作成してみる

それでは、実際に仮想環境を作成してみましょう。

まずは、作業用ディレクトリを用意します。

mkdir ~/Developer/python-learning
cd ~/Developer/python-learning

続いて、

python3 -m venv .venv

を実行します。

一見すると一瞬で終わるため、

「何も起きていないのでは?」

と思うかもしれません。

しかし、実際にはプロジェクト内に新しいディレクトリが作成されています。

まずは通常の ls を実行してみます。

ls

すると、何も表示されません。

これは、

.(ドット)から始まるファイルやディレクトリは、デフォルトでは表示されない

ためです。

そこで、

ls -a

を実行してみます。

すると、

.
..
.venv

のように表示されます。

つまり、

仮想環境は .venv という隠しディレクトリとして作成される

ことが分かります。

ここからが本記事の本題です。

次は、この .venv ディレクトリの中身を詳しく見ていきます。

.venv の中身を確認してみる

それでは、実際に .venv の中身を確認してみましょう。

まず、

ls .venv

を実行します。

私の環境では、次のように表示されました。

bin
include
lib
pyvenv.cfg

つまり、.venv の中には、

.venv/
├── bin/
├── include/
├── lib/
└── pyvenv.cfg

という構造が作られています。

一見すると単純ですが、それぞれ重要な役割を持っています。

ここからは、

  1. pyvenv.cfg
  2. bin
  3. lib
  4. include

の順番に見ていきます。

pyvenv.cfg とは何か

まず、

pyvenv.cfg

から確認します。

cat .venv/pyvenv.cfg

を実行すると、私の環境では次のように表示されました。

home = /opt/homebrew/opt/python@3.14/bin
include-system-site-packages = false
version = 3.14.6
executable = /opt/homebrew/Cellar/python@3.14/3.14.6/Frameworks/Python.framework/Versions/3.14/bin/python3.14
command = /opt/homebrew/opt/python@3.14/bin/python3.14 -m venv /Users/yhiraiwa/Developer/python-lerning/.venv

いきなり見ると、少し難しそうです。

しかし、順番に見ていけば、それぞれ何を意味しているのか分かります。

home について

まず、

home = /opt/homebrew/opt/python@3.14/bin

です。

これは、仮想環境の作成に使用したPython環境の場所を示しています。

今回の環境では、HomebrewによってPython 3.14がインストールされています。

以前確認したように、

which python3

を実行すると、

/opt/homebrew/bin/python3

となっていました。

そして、

ls -l /opt/homebrew/bin/python3

を実行すると、

/opt/homebrew/bin/python3 -> ../Cellar/python@3.14/3.14.6/bin/python3

のようなシンボリックリンクになっています。

つまり、

/opt/homebrew/bin/python3
        │
        │ シンボリックリンク
        ▼
/opt/homebrew/Cellar/python@3.14/...
        │
        ▼
   Python本体

という構造です。

pyvenv.cfg の

home = /opt/homebrew/opt/python@3.14/bin

も、このHomebrew版Pythonを基準に仮想環境が作成されたことを示しています。

include-system-site-packages について

次に、

include-system-site-packages = false

です。

これは、

システム側のPythonにインストールされているパッケージを、仮想環境から利用するか

を指定しています。

今回の設定は、

false

なので、

システム側のPythonパッケージを仮想環境に含めない

という設定になっています。

これは仮想環境の重要な特徴です。

仮想環境の目的は、

プロジェクトごとにPythonパッケージを分離すること

だからです。

例えば、仮想環境の外側に

numpy
matplotlib
scipy

がインストールされていたとしても、通常はそれらをそのまま利用するのではなく、現在のプロジェクトの仮想環境に必要なパッケージをインストールします。

イメージとしては、

Mac全体
│
├── Homebrew Python
│
│
├── プロジェクトA
│   └── .venv
│       ├── numpy
│       └── matplotlib
│
└── プロジェクトB
    └── .venv
        ├── numpy
        └── scipy

というように、それぞれのプロジェクトを分離できます。

これによって、

プロジェクトAのnumpy

と

プロジェクトBのnumpy

を別々のバージョンで管理することも可能になります。

version について

次に、

version = 3.14.6

です。

これは、その仮想環境を作成したPythonのバージョンを示しています。

今回の場合は、

Python 3.14.6

です。

これは、仮想環境を作成する前に確認した、

python3 --version

の結果と対応しています。

つまり、

Homebrew Python 3.14.6
        │
        │
        ▼
python3 -m venv .venv
        │
        ▼
      .venv
        │
        └── version = 3.14.6

という関係になっています。

executable について

続いて、

executable = /opt/homebrew/Cellar/python@3.14/3.14.6/Frameworks/Python.framework/Versions/3.14/bin/python3.14

です。

これは、

仮想環境を作成するときに使用されたPython実行ファイル

を示しています。

ここで、

/opt/homebrew/Cellar/

というディレクトリが出てきました。

Homebrewでは、インストールされたソフトウェアの実体が、

/opt/homebrew/Cellar/

以下で管理されています。

一方、

/opt/homebrew/bin/

には、ユーザーがコマンドとして実行するためのシンボリックリンクが配置されます。

そのため、

/opt/homebrew/bin/python3

と、

/opt/homebrew/Cellar/python@3.14/...

は別の場所ですが、リンクによってつながっています。

command について

最後に、

command = /opt/homebrew/opt/python@3.14/bin/python3.14 -m venv /Users/yhiraiwa/Developer/python-lerning/.venv

です。

これは、

この仮想環境を作成する際に実行されたコマンド

を示しています。

今回、自分で実行したコマンドは、

python3 -m venv .venv

でした。

これを具体的なPythonのパスに置き換えると、

/opt/homebrew/opt/python@3.14/bin/python3.14 -m venv /Users/yhiraiwa/Developer/python-lerning/.venv

となります。

つまり、

Python
  │
  ├── -m
  │
  └── venv
        │
        └── .venvを作成

という処理を行ったわけです。

python3 -m venv .venv をもう一度理解する

ここで、仮想環境を作成するときに使用した、

python3 -m venv .venv

というコマンドを改めて見てみましょう。

このコマンドは4つの部分に分けて考えると分かりやすくなります。

python3
-m
venv
.venv

それぞれ、

python3

はPythonを実行することを意味します。

-m

は、Pythonのモジュールを実行するためのオプションです。

venv

は、Pythonに標準で用意されている仮想環境作成用のモジュールです。

そして、

.venv

は、作成する仮想環境のディレクトリ名です。

したがって、

python3 -m venv .venv

とは、

Pythonを使って標準ライブラリのvenvモジュールを実行し、現在のディレクトリに.venvという仮想環境を作成する

という意味になります。

これは非常に重要なので、ぜひ覚えておきましょう。

bin ディレクトリ

次に、

bin

を確認します。

ls .venv/bin

を実行します。

私の環境では、

Activate.ps1
activate
activate.csh
activate.fish
pip
pip3
pip3.14
python
python3
python3.14

などが表示されました。

ここには、

  • Python
  • pip
  • 仮想環境を有効化するためのスクリプト

などが入っています。

特に重要なのが、

python
python3
pip
activate

です。

.venv/bin/python3 について

では、

ls -l .venv/bin/python3

を実行してみましょう。

すると、

.venv/bin/python3 -> ...

のような表示になります。

ここで重要なのが、

->

です。

これはシンボリックリンクを示しています。

つまり、

.venv/bin/python3

が、Pythonの実体そのものではなく、

別のPython実行ファイルを指している

ことを意味します。

概念的には、

.venv/bin/python3
        │
        │ シンボリックリンク
        ▼
HomebrewでインストールされたPython

という関係です。

ここから、

venvはPythonを丸ごとコピーしているわけではない

ということが分かります。

lib ディレクトリ

次に、

lib

を見てみましょう。

ls .venv/lib

すると、Pythonのバージョンに対応したディレクトリが存在します。

今回のPythonは3.14なので、

python3.14

というディレクトリがあります。

さらに、

ls .venv/lib/python3.14

とすると、

site-packages

というディレクトリがあります。

この、

site-packages

が非常に重要です。

site-packages とは何か

Pythonの外部パッケージは、基本的にこの

site-packages

にインストールされます。

例えば、仮想環境を有効化した状態で、

python3 -m pip install numpy

を実行すると、

.venv/lib/python3.14/site-packages/

の中にNumPyがインストールされます。

同様に、

python3 -m pip install matplotlib

を実行すれば、Matplotlibもこの場所にインストールされます。

つまり、

.venv/
└── lib/
    └── python3.14/
        └── site-packages/
            ├── numpy/
            ├── matplotlib/
            └── ...

という構造になります。

これが、

プロジェクトごとにPythonパッケージを分離する

仕組みの中心です。

include ディレクトリ

最後に、

include

です。

これは、PythonのC拡張などをコンパイルするときに必要となるヘッダファイルなどに関連するディレクトリです。

Pythonのパッケージには、Pythonだけで実装されているものだけではありません。

例えば、

  • C
  • C++
  • Fortran

などで実装されたコードを内部で利用するパッケージもあります。

特にNumPyのような数値計算ライブラリでは、Pythonだけではなく、コンパイルされたコードが重要な役割を果たします。

そのため、仮想環境には、

include

というディレクトリも用意されています。

ただし、通常のPythonプログラミングでは、このディレクトリを直接操作することはほとんどありません。

ここでは、

C/C++などと連携する際に利用される場所

くらいに理解しておけば十分です。

.venv 全体を整理する

ここまでの内容をまとめると、.venv は次のような構造になっています。

.venv/
│
├── bin/
│   ├── python
│   ├── python3
│   ├── pip
│   └── activate
│
├── include/
│
├── lib/
│   └── python3.14/
│       └── site-packages/
│           ├── numpy
│           ├── matplotlib
│           └── ...
│
└── pyvenv.cfg

それぞれの役割を表にすると、

ファイル・ディレクトリ 役割
bin/ Python、pip、activateなどの実行用ファイル・スクリプト
lib/ Pythonライブラリを格納する場所
site-packages/ pipでインストールしたパッケージが入る場所
include/ C/C++などとの連携に必要なヘッダ関連
pyvenv.cfg 仮想環境の設定情報

となります。

ここまで理解できれば、

python3 -m venv .venv

によって「何が作られているのか」がかなり見えるようになったと思います。

仮想環境を作っただけでは、まだ切り替わっていない

ここで、非常に重要な点があります。

python3 -m venv .venv

を実行したからといって、

その瞬間から仮想環境のPythonが使われるわけではありません。

仮想環境を作ることと、仮想環境を利用することは別だからです。

例えば、仮想環境を作成した直後に、

which python3

を実行してみます。

まだ仮想環境を有効化していなければ、

/opt/homebrew/bin/python3

のように表示されます。

つまり、

python3
  │
  ▼
/opt/homebrew/bin/python3

となっています。

まだ、

.venv/bin/python3

には切り替わっていません。

「作る」と「有効化する」は別

ここは今後のPython環境を理解するうえで非常に重要なので、もう一度整理します。

仮想環境を作るコマンドは、

python3 -m venv .venv

です。

一方、仮想環境を有効化するコマンドは、

source .venv/bin/activate

です。

つまり、

① 仮想環境を作成

python3 -m venv .venv
        │
        ▼
      .venv/

と、

② 仮想環境を有効化

source .venv/bin/activate
        │
        ▼
現在のシェルが .venv を使うようになる

は、別々の操作です。

今回の重要ポイント

今回、一番覚えておいてほしいことは次の3つです。

① .venv は単なる空のフォルダではない

中には、

bin
include
lib
pyvenv.cfg

があり、それぞれ役割があります。

② Pythonパッケージは site-packages に入る

例えば、

python3 -m pip install numpy

を仮想環境内で実行すると、

.venv/lib/python3.14/site-packages/

にNumPyがインストールされます。

③ 仮想環境を作ることと有効化することは別

python3 -m venv .venv

は、

仮想環境を作る

コマンドです。

source .venv/bin/activate

は、

仮想環境を現在のシェルで使う

ためのコマンドです。

次回予告

ここまでで、

「仮想環境という箱がどのように作られているのか」

が分かりました。

しかし、まだ一つ大きな疑問が残っています。

なぜ、

source .venv/bin/activate

と入力するだけで、

which python3

の結果が

/opt/homebrew/bin/python3

から

/Users/yhiraiwa/Developer/python-lerning/.venv/bin/python3

へ変わるのでしょうか?

そして、ターミナルの先頭に、

(.venv)

と表示されるのはなぜでしょうか?

次回は、この疑問を解決します。

次回のテーマは、

「activateの正体」

です。

source .venv/bin/activate

という一行の裏側で、

  • source は何をしているのか
  • activate は何をしているのか
  • PATH はどのように変更されるのか
  • VIRTUAL_ENV とは何か
  • (.venv) が表示される理由
  • deactivate は何をしているのか
  • hash -r は何のためにあるのか

を、実際の activate スクリプトを読みながら詳しく見ていきます。

「activateすればPythonが切り替わる」という暗記から一歩進んで、

「なぜ切り替わるのか」

を理解することが次回の目標です。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?