Python venvの使い方

Pythonの仮想環境は使わずに来たんだけど、f文字列の仕様が良くなったVer. 3.12を使いたくなって、仮想環境に手を出すことにした。venvを使おうとしたら、きちんと説明しきっているものが少なかったので、確認した結果を以下にまとめます。

# venvとは

- pythonに標準で入っている仮想環境構築ツールであるゆえ、追加インストールが不要
- シンプルな仕組みとなっていて理解し易い
- ライブラリーのインストールなどには、pipが標準状態と同じ様に使える

# 仕組み

- 仮想環境構築時に、指定ディレクトリーの下に、Pythonインタープリターの実行ファイルをコピーするかシンボリックリンクファイルを作成するかし、ライブラリーのsite package用ディレクトリーを空の状態で作成する
- その際に、その実行ファイルのディレクトリーやライブラリーのディレクトリーを使うように環境変数を設定するスクリプトファイルを生成する
- また同時に、仮想環境構築前の環境変数の設定に戻すためのスクリプトファイルも生成する
- 仮想環境に関わる設定を記録したファイル```pyvenv.cfg```が作成される
- これらのスクリプトファイルにより設定される環境変数により、Pythonインタープリターの実行ファイル、ライブラリーをインストールするディレクトリー、ライブラリーを探すディレクトリーが切り替えられる
- 作成された```pyvenv.cfg```ファイルは、Pythonインタープリターの実行ファイルは起動時に自動的に見つけられ、標準ライブラリーの置かれているディレクトリーなどが認識される

# 使い方

## 仮想環境構築

コマンドプロンプトまたはシェルで以下のように実行する

```bat
PathToPythonExt\python -m venv PathToVenvDir
```


:::note info
補足説明

- コマンドとして、作成する仮想環境で使いたいバージョンのPythonインタープリターの実行ファイルを指定する
    - PATHサーチで見つかるものが使いたいものに一致する場合には`PathToPythonExt\`の部分は不要
    - インストール済みの最新版のPythonインタープリターの実行ファイルを指定したい場合には、`PathToPythonExt\python`の代わりに`py`と指定しても良い
    - インストール済みのあるバージョンのPythonインタープリターの実行ファイルを指定したい場合には、`PathToPythonExt\python`の代わりに`py -3.9`などとpyコマンドでバージョンを指定しても良い
- 引数`-m venv` で、標準ライブラリーのvenvのimportと実行を指定している

- venvについての説明で、`PathToVenvDir`の部分が単に`venv`とだけなっていて、パス情報を含まないものが多いが、これはカレントディレクトリーの下に仮想環境用のディレクトリーを作成することを想定している。カレントディレクトリーの下では無い場所に仮想環境用のディレクトリーを作成したい場合には、パス情報を含めて`PathToVenvDir`の部分を指定のこと
::::

これにより指定ディレクトリー以下に、Pythonインタープリターの実行ファイルのコピーまたはシンボリックリンクファイル、追加ライブラリーインストール用のディレクトリー、アクティベーション用のバッチファイルなどが用意される。

:::note info
MS-Windowsにおいては、シンボリックリンクファイルを用いると、指定したものと異なるPythonインタープリターの実行ファイルが実行されてしまうことがあるとのことで、シンボリックリンクの作成ではなく、コピーがされる
:::

## アクティベーション(仮想環境の有効化)

作成した仮想環境に切り替えて作業する際には毎回、コマンドプロンプトやシェルを開き、仮想環境用ディレクトリーの下の以下のファイルのいずれかを実行する。そのコマンドプロンプトやシェルのプルセスと、その子プロセスは指定した仮想環境の下で動作する。

| プラットフォーム | シェル | 仮想環境を有効化するためのコマンド |
| --- | --- | --- |
| POSIX | bash/zsh | $ source <venv>/bin/activate |
|  | fish | $ source <venv>/bin/activate.fish |
|  | csh/tcsh | $ source <venv>/bin/activate.csh |
|  | PowerShell | $ <venv>/bin/Activate.ps1 |
| Windows | cmd.exe | C:\> <venv>\Scripts\activate.bat |
|  | PowerShell | PS C:\> <venv>\Scripts\Activate.ps1 |
- 仮想環境が有効になっている状態では、pipコマンドは仮想環境用ディレクトリーの下の追加ライブラリーインストール用のディレクトリーに対して動作する
- jupyterなどの外部プログラムをこの仮想環境下で動作させるには、その起動用バッチファイルなどの最初に、`call C:\venv\Scripts\activate`の様にアクティベーション用バッチをそのプロセス内で実行するコマンドを追加し、それを用いるようにする。
    - jupyterlabの起動用バッチをその様にした例を以下に示す
    
```bat
cd %USERPROFILE%\Documents
call C:\venv\Scripts\activate.bat
jupyter.exe lab --port 8888
```
    

## インストール済みライブラリーの移行

### venvにおけるライブラリーの扱い

- 仮想環境はプロジェクト固有の依存関係を分離して管理するものである
- よって、仮想環境構築直後は標準以外のライブラリーが「空」の状態とする
- このため、仮想環境内で必要とされるすべてのライブラリは、その環境をアクティブにした状態で、明示的にインストールする必要がある。
- これにより、プロジェクト間での依存関係の衝突を避け、より一貫性のある開発とテストの環境が提供される。

### Case A: 同一バージョンのライブラリーを用いる場合

テスト環境構築として仮想環境を利用する場合など、既にインストール済みのライブラリーと同一のバージョンのものを新しい仮想環境にインストールする場合には、以下のようにする

#### インストール済みパッケージリストの取得
移行元の環境で以下を実行

```bat
pip freeze > requirements.txt
```

:::note info
このrequirements.txtには各ライブラリーの使用されているバージョン番号と同じバージョンのものを使う指定がされている
::::
    
#### 仮想環境へのインストール
    
アクティベートされた仮想環境で以下を実行
```bat
    pip install -r requirements.txt
```
    

:::note warn
使用するPythonインタープリターの実行ファイルのバージョンが変わっている場合には、この方法ではエラーが出てうまくいかないことがある。
(例：Pythonインタープリターの最新版への対応が、そのライブラリーの最新版で行われていて、移行元の環境では古いライブラリーを用いていた場合)
**その様な場合には、Case Bの方法を用いる**こと。

:::

### Case B: 同じライブラリーの最新バージョンを用いる場合

Pythonインタープリターの新しいバージョンに移行したい場合などで、以前の環境で使っていたのと同じライブラリーを使いたいが、ライブラリーのバージョンにこだわりがなく、最新版のライブラリーがインストールされても構わない場合には、以下のようにする

#### ライブラリーリストを用意
    
以下の様に、使いたいライブラリーを1行ごとに書いたファイル(common-requirements.txt)を用意する

:::note info
pipコマンドを個別に行うことでも可能だが、この方法の方が色々便利！
:::
    
```
# This file is requirements.txt file of pip to define commonly installed library for me.
# このファイルは、python pipコマンドで用いるrequirements.txtファイルで、標準的にインストール
# したいライブラリーを定義したものです。
#
# Usage: pip install -r common-requirements.txt
#
numpy
pandas
matplotlib
jupyter
jupyterlab
ipywidgets
fire
xlwings
pywin32
pillow
```

:::note info
上記の様にこのファイル中に日本語文字を含む場合には、このファイルはShift-JIS形式(cp932形式)で保存しておかないと、pipコマンド実行時にエラーとなる
    (pipコマンドがOSのデフォルト文字コードを想定しているため)
:::

#### 仮想環境へのインストール
    
アクティベートされた仮想環境で以下を実行することで同じライブラリーが仮想環境にインストールされる
    
```bat
pip install -r common-requirements.txt
```

# まとめ
説明がさらっとしすぎてる感じなので、venvの使い方で重要な点を以下にまとめます。

- 「仕組み」として書いたように、環境変数の設定によって、仮想環境の切り替えが行われるゆえ、**自プロセス内**でその環境変数を設定するスクリプト(actibate.batなど)を実行しなくてはいけない。
(bash上であれば、シェルスクリプトとして実行ではなく、sourceコマンドを用いて実行する)

    - 逆に言うとその環境変数の設定さえすれば、指定の仮想環境下で動作することになるので、指定の仮想環境下で動作させたいプログラムなどの起動用スクリプト中で環境変数の設定が行われるようにすれば良い。

- 仮想環境をどのバージョンのpythonとするかは、仮想環境作成時に用いられるpythonインタプリターの実行ファイルで決まる。