Pythonにおける仮想環境「pyenv」について

# 1. はじめに

「[Pythonにおける仮想環境「venv」について](https://qiita.com/overflowfl/items/1db8746b9831bb15e9b5)」にて、python仮想環境として**venv**を使うべしと紹介いたしましたが、**pyenv＋virtualenv**には**venv**に無い良い点があります。
本稿ではそれぞれのメリット・デメリットと、**pyenv＋virtualenv**の環境構築方法について紹介いたします。

# 2. メリット・デメリット
それぞれのメリット・デメリットは以下の通りです。

| 方式 | メリット | デメリット |
|---|---|---|
| venv | ・環境に依らず利用可能 | ・作った仮想環境を複数のプロジェクトで共有できない。<br>・python本体の導入は別途自分でやる必要がある。 <br>・仮想環境を切り替える際にactivateコマンドを実行する必要がある|
| pyenv＋virtualenv | ・複数のプロジェクトで共有も可能。<br>・python本体の導入も面倒を見てくれる。 <br>・ディレクトリ毎に仮想環境を設定することができる。（いちいちactivateコマンドを実行しなくてもディレクトリ移動で勝手に環境がスイッチされる）| ・Linux（MACもOK）じゃないと利用できない。<BR>・インストール作業が必要。 |

上述の通り、**pyenv＋virtualenv**はpythonの導入も面倒を見てくれるため、複数バージョンのpythonをプロジェクトに応じて切り替える必要がある場合は、大変重宝します。しかも、ディレクトリ単位に仮想環境を設定でき、いちいちactivateコマンドを実行しなくても、ディレクトリ移動で仮想環境が勝手に切り替わってくれます。一方、venvの場合は自前でpython導入・管理をする必要があり、切り替えに当たってはactivateコマンドを実行する必要があるので手間です。特に複数バージョンのpythonを使い分けるという場合は大変手間がかかります。[^1]

# 2. pyenv+virtualenvのインストール

## 2-1 gitのインストール
pyenvとpyenv-virtualenvのインストールに当たって、gitからコードを取得する必要があるためgitコマンドを導入します。

~~~
$ sudo apt install -y git
~~~

## 2-2 pyenvのインストール
pyenvをgitから取得し、.profileに設定を行います。

~~~
$ git clone https://github.com/pyenv/pyenv.git ~/.pyenv
$ vi ~/.profile
***以下を最後尾に追記***
export PYENV_ROOT=$HOME/.pyenv
export PATH=$PYENV_ROOT/bin:$PATH
if command -v pyenv 1>/dev/null 2>&1; then
  eval "$(pyenv init -)"
fi
******
$ source ~/.profile
~~~

## 2-3 pyenv-virtualenvのインストール
pyenv-virtualenvをgitから取得し、.profileに設定を行います。

~~~
$ git clone https://github.com/yyuu/pyenv-virtualenv.git ~/.pyenv/plugins/pyenv-virtualenv
$ vi ~/.profile
***以下を最後尾に追記***
eval "$(pyenv virtualenv-init -)"
******
$ source ~/.profile
~~~

2-4. sudoersの設定
Ubuntuの環境に導入する際に必要な設定のようです。

~~~
$ sudo groupadd developer
***【USERNAME】はログインユーザ名***
$ sudo gpasswd --add 【USERNAME】 developer
$ sudo visudo
***以下の通り変更・追加***
Defaults        exempt_group="developer"
******
~~~

以上で環境が整いました。


# 3. pyenvを用いたpythonのインストール

## 3-1 下準備
pyenvでpythonをインストールする際に、pythonのコンパイルが実行されるため、必要なパッケージをあらかじめ導入します。
※必要なパッケージはpythonのバージョンによって異なります。以下は3.7.3を導入する際に必要なパッケージです。

~~~
$ sudo apt -y install build-essential libffi-dev libssl-dev libreadline6-dev zlib1g-dev libbz2-dev libsqlite3-dev sqlite3
~~~


## 3-2 pythonインストール
続いてpythonの導入を行います。なお、OSが標準で入れているPythonとは別の管理になるので、複数のバージョンを入れても、この時点では全く影響ないです。

~~~
インストール可能なpythonのバージョンをリスト表示
$ pyenv install --list 

pythonのインストール
$ pyenv install 3.7.3

導入されているpythonの確認
$ pyenv versions
* system (set by /home/xxxxxxxx/.pyenv/version)
  3.7.3
~~~
現在のフォルダに適用されているpythonのバージョンの左側に **　*　** がつきます。


# 4. pyenv-virtualenvを用いた仮想環境の作成と適用
上記作業にて、複数バージョンのpythonを切り替えて利用できるようになります。このまま利用可能ですが、仮想環境を構築します。[^2]

## 4-1 仮想環境作成
~~~
testという名前でpython3.7.3の仮想環境を構築
$ pyenv virtualenv 3.7.3 test

導入されているpythonの確認
$ pyenv versions
* system (set by /home/xxxxxxxx/.pyenv/version)
  3.7.3
  3.7.3/envs/test
~~~

## 4-2 仮想環境の適用
プロジェクトのディレクトリに対して、作成した仮想環境を適用します。

~~~
$ cd test_project
$ pyenv versions
* system (set by /home/xxxxxxxx/.pyenv/version)
  3.7.3
  3.7.3/envs/test

仮想環境設定
$ pyenv local test
(test) $
~~~

仮想環境が設定されると、プロンプトの前に**(test)**のようにカッコ書きで仮想環境名がつきます。
この状態で、**pyenv versions**を実行します。

~~~
(test) $ pyenv versions
  system
  3.7.3
  3.7.3/envs/test
* test (set by /xxxxxxxx/test_project/.python-version)
~~~

先ほど**system**に付いていた**　*　** が新たに追加されたtestという定義に移動しています。
改めて、他のフォルダに移動してみると、sysytemに戻ります。

~~~
(test) $ cd ..
$ pyenv versions
* system (set by /home/xxxxxxxx/.pyenv/version)
  3.7.3
  3.7.3/envs/test
  test
~~~

各仮想環境に入れたライブラリ（モジュール）は他の環境に影響しません。
例えば、**test2**という環境を作成し、その環境に**six**を入れても**test**には影響しません。
実際に試してみたいと思います。


仮想環境**test**に何もライブラリが導入されていないことを確認
~~~
$ cd test_project
(test) $ pip freeze
~~~

仮想環境**test2**を新たに作成し、仮想環境をスイッチしたうえでsixをインストール

~~~
(test) $ pyenv virtualenv 3.7.3 test2
(test) $ pyenv local test2
(test2) $ pip freeze
(test2) $ pip install six
(test2) $ pip freeze
six==1.12.0
~~~

仮想環境をtestにスイッチして改めてsixが入っていないことを確認

~~~
(test2) $ pyenv local test
(test) $ pip freeze
(test) $
~~~

なお、**.python-version**というファイルを削除すると、仮想環境の設定がキャンセルされます。

~~~
(test) $ rm .python-version
$ pyenv versions
* system (set by /home/xxxxxxxx/.pyenv/version)
  3.7.3
  3.7.3/envs/test
  3.7.3/envs/test2
  test
  test2
~~~

# 5. プロジェクトフォルダ共有における注意点について

注意点はvenvの時と同様です。仮想環境は各自が作るものなので、プロジェクトフォルダをgitなどで共有する際は**.python-version**は除外するべきです。また、venv同様pipで導入する必要があるライブラリが分かるように、**requirements.txt**を配置しておくべきです。

# 6. おわりに
venvに続きpyenv+virtualenvについて紹介いたしました。どちらを選択するか検討する際の一助になれば幸いです。



[^1]: Windowsの場合、複数のpythonを導入して切り替える場合は、**py.exe**を使うことになります。py.exeはwindows10に標準で用意されているプログラムです。


[^2]: 複数のプロジェクトで同じversionのpythonを使い分ける場合において、ライブラリ（モジュール）の競合が発生してしまう可能性があるので、