Pythonの仮想環境構築
はじめに
Pythonにおける仮想環境構築について、python で仮想環境を構築するツールは以下のようにたくさんの種類があります。はじめに各種仮想環境作成ツールについての簡単な説明を行います。
Python の仮想環境作成ツールの主な分類について。
- Python(インタプリタ)のバージョン切り替えを行うもの
- パッケージ切り替えを行うもの
- 2の機能に加えて独自のパッケージ管理機能を有するもの(pip以外のパッケージ管理を利用可能なもの)
| 1. インタプリタ | 2. パッケージ | 3. 独自パッケージ管理 | |
|---|---|---|---|
| venv | ○ | ||
| virtualenv | ○ | ○ | |
| pyenv | ○ | ||
| pyenv-virtualenv | ○ | ○ | |
| pipenv | ○ | ○ | |
| anaconda | ○ | ○ | ○ | 
ツールの比較や歴史的経緯は以下の記事が参考になります。
実行環境
- OS: Ubuntu 20.04.4 LTS (Focal Fossa)
- shell: zsh 5.8 (x86_64-ubuntu-linux-gnu)
pyenvとは
pyenv は、複数のバージョンの Python を簡単に切り替えることができます。
pyenv は shell を常に監視して、ユーザーが python を利用する時に仮想環境の python を渡すことで、様々なバージョンの python を切り替えて利用できるという仕組みです。
もともとは rbenv と呼ばれる ruby 用の仮想環境構築ツールから派生して作られています。
この記事では、pyenv では基本的にパッケージをインストールせず、利用したいPythonバージョンを切り替えるために使います。パッケージ管理には Pipenv や Poetry などを使うことを想定しています。
Pyenv本体のインストール
pyenvをインストールしていきます。
依存関係にあるライブラリをインストール
はじめに、依存関係のあるライブラリをインストールしていきます。
sudo apt update; sudo apt install -y make build-essential libssl-dev zlib1g-dev \
libbz2-dev libreadline-dev libsqlite3-dev wget curl llvm \
libncursesw5-dev xz-utils tk-dev libxml2-dev libxmlsec1-dev libffi-dev liblzma-dev \
git
pyenvをダウンロード
gitコマンドで pyenv をダウンロード(clone)します。
git clone https://github.com/pyenv/pyenv.git ~/.pyenv
git cloneコマンドについて
git clone <ダウンロード元のレポジトリ> <ダウンロードするディレクトリ>
上記のコマンドでは pyenvの公式レポジトリから~./pyenv に保存しています。
~や$HOME はホームディレクトリを表します
ダウンロード場所を変更する場合は、以下のpathを通す作業時にダウンロード場所を指定して下さい。
PATHを通す
先程ダウンロード(clone)したディレクトリ内にある、pyenvの実行ファイルへのPATHを通します。この作業を行うことで、pyenvコマンドが利用可能になります。
# 1. "$HOME/.pyenv" は先程ダウンロードしたディレクトリ path 入力する
echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.zshrc
# 2. Pathを通す
# 環境変数 $PATH に先程ダウンロードしたディレクトリ内の実行ファイルを登録する
echo 'export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.zshrc
# 3. pyenvコマンドを初期化する
echo 'eval "$(pyenv init --path)"' >> ~/.zshrc
シェルの種類を確認する
echo $SHELL
Bashを利用している場合
echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.bashrc
echo 'export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.bashrc
echo 'eval "$(pyenv init --path)"' >> ~/.bashrc
PATHを追加した ~/.zshrc または ~/.bashrc を再読込します。
source ~/.zshrc
Bashを利用している場合
source ~/.bashrc
使い方
インストールが完了していることを確認するため、「pyenv」のバージョンを確認します。
pyenv -v
バージョンが表示されれば、PyenvがインストールされておりPathが通っています。
インストール可能なPythonのバージョンを表示
インストール可能な「python」のバージョンを表示します。
pyenv install --list
Python をインストール
python` のバージョンを指定してインストールしていきます。
pyenv install 3.10.0
インストールが完了したか確認する。
インストールが正常に完了していたら、先程インストールした3.10.0が表示されます。
現在利用している「python」の頭に*が表示されています。
pyenv versions
* system (set by /home/mook/bin/pyenv/version)
  3.10.0
Pythonのバージョンを変更
- 現在のユーザーで利用するpythonのバージョン変更します。(全ディレクトリ)
pyenv global 3.10.0 # Python 3.10.0を利用する
- 現在のディレクトリで利用するバージョンを変更する
pyenv local 3.10.0 # Python 3.10.0を利用する
設定中のPythonのバージョンを表示
現在設定中の「python」のバージョンを表示する。
デフォルトではシステム用にインストールされている「python」のバージョンが表示されます。
- 
pyenvでインストールされているPythonのバージョンを一覧表示する。有効化されているバージョンは行頭に*(アスタリスク)がついています。
pyenv versions
- pyenvで有効になっているPythonのバージョンを表示する。
pyenv version
- 
OS(bashやzsh)で有効になっているpythonのバージョンを確認する。
python -V
- 有効になっているPythonの実行ファイルがある場所を表示
which python
pyenvの各バージョンのインストール場所について
pyenv install <version>コマンドでインストールしたPythonは以下の場所に保管されています。$HOME/.pyenvは最初に pyenv をダウンロードした場所です。
$HOME/.pyenv/shims/               # pyenvの仕組みの核。
          |-/versions             # インストールしたPythonの格納場所
                   |-/2.7.8/      # Python 2.7.8
                   |-/3.4.2/      # PYthon 3.4.2
                   |-/pypy-2.4.0/ # PYPY 2.4.0
          |-/version              # globalで使うpythonのバージョン情報ファイル
pyenv でバージョン切り替えができない場合
バージョンの切り替えができない場合は、以下のような箇所を確認すると良いです。
1. pyenvコマンドが command not found となるとき
PATHが通っていません。pathが登録されているか確認しましょう。
pyenvのPATHが通っている場合は、 echo $PATH コマンドを実行した時に、<pyenvをダウンロードしたディレクトリ>/binが表示されます。
出力はディレクトリのPATH1:ディレクトリのPATH2:...のように表示されます。
echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin
出力を見やすく改行
echo $PATH
/usr/local/sbin:
/usr/local/bin:
/usr/sbin:
/usr/bin:
/sbin:
/bin:
/usr/games:
/usr/local/games:
/snap/bin
ダウンロードした、pyenvのディレクトリが表示されていない場合はPATHを通すをご確認くださいを確認してください。
2. pyenvコマンドは使えるが、 Pythonのバージョンが切り替わらない
pyenvの初期化に失敗しています。echo $PATHを実行し、<pyenvをダウンロードしたディレクトリ>/bin/shimsが表示されるか確認します。
echo $PATH
/home/mook/.pyenv/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin
通っていない場合は、以下のコマンド実行します。
eval "$(pyenv init --path)"
これで python -V で有効になっていれば大丈夫です。
ログイン時に有効になるように以下の、コマンドを実行してください。
echo 'eval "$(pyenv init -)"' >> ~/.zshrc
bashの場合
echo 'eval "$(pyenv init -)"' >> ~/.bashrc
※ その他詰まったことがあればコメントください。
よくあるパターン
初めて pyenv をインストールして使うまで。
# pyenvはインストールされている
$ pyenv -v
pyenv 2.2.5-9-g72757562
# インストールされているバージョンを表示する
$ pyenv versions
* system (set by /home/mook/.pyenv/version)
# pythonのバージョンを確認する。まだpyenvでインストールしていないからだと思い込む
$ python -V
zsh: command not found: python
# なぜか python3 コマンドは利用できる
$ python3 -V
Python 3.8.10
# python3コマンドはどこにインストールされている?
# OSに標準インストールされているPython
$ which python3
/usr/bin/python3
# とりあえず、pythonをインストールしてみる
$  pyenv install 3.8.10
Downloading Python-3.8.10.tar.xz...
-> https://www.python.org/ftp/python/3.8.10/Python-3.8.10.tar.xz
Installing Python-3.8.10...
Installed Python-3.8.10 to /home/mook/.pyenv/versions/3.8.10
# ちゃんとインストールされている
$ pyenv versions
* system (set by /home/mook/.pyenv/version)
  3.8.10
# インストールされたpythonを有効化してみる
$ pyenv global 3.8.10
# ちゃんと有効化されている
$ pyenv versions
  system
* 3.8.10 (set by /home/mook/.pyenv/version)
# まだ python コマンドは使えない、ここで焦る。
$ python -V
zsh: command not found: python
# python3 コマンドは使える。
# 以下のような、思考が頭をよぎります。
#   - `python`コマンドが使えないだけだと思い込む。
#   - 出力されたバージョンは先程インストールしたものだし大丈夫だろう。
$ python3 -V
Python 3.8.10
大抵このパターンはPythonの新バージョンが出て、新機能を試したりすると、有効になっていないことに気づきます。
# 初めて使う時はちゃんとコマンドの場所を確認しましょう
$ which python3
登録されているPATHを確認してみましょう
- pyenvコマンドにPATHが通っていない場合
echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin
- pyenvにPATHが通っている場合(pyenvの初期化ができていない場合)
 /home/mook/.pyenv/bin(pyenvをダウンロードした場所)が追加されています。
echo $PATH
/home/mook/.pyenv/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin
- pyenvが正常に有効化されている
 /home/mook/.pyenv/shimsが追加されています。
echo $PATH
/home/mook/.pyenv/shims:/home/mook/.pyenv/bin:/home/mook/.pyenv/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin
pyenvのチートシート
各オプションは以下のように利用します。
pyenv <オプション>
| オプション | 説明 | 
|---|---|
| --version | pyenvのバージョンを表示します | 
| commands | 利用可能なpyenvのコマンドを一覧表示します。--helpの説明がないコマンド一覧が表示されます。 | 
| exec | 選択されたPythonのバージョンで実行ファイルを実行する。例: pyev exec pip install Flaskなどの実行可能ファイルを実行することができる。linuxではBourne-Again shell script(Bash Script)などを実行することができます。pip自体も中身はBash Scriptです。なお、実行時はコマンドとして登録されている場合はそのまま使えますが、ファイル形式のものを利用する場合は、pyenv exec ./test.shなどのように./を頭につけないと実行できません。 | 
| shell | 現在のシェルのみに有効なPythonのバージョンを設定または表示 | 
| local | ローカル(特定ディレクトリで有効)なPythonのバージョンを設定または表示 | 
| global | グローバル(全ディレクトリで有効)なPythonのバージョンを設定または表示 | 
| help | コマンドの一覧と説明を表示する | 
| hooks | 指定されたpyenvコマンドのフックスクリプトを一覧表示します。https://github.com/pyenv/pyenv/wiki/Authoring-plugins#pyenv-hooks | 
| init | pyenvのためのシェル環境の設定。 eval "$(pyenv init --path)"と~/.bashrc等へ記載することでpythonを実行する時にpyenv側でコマンドを受け取ってpyenvで管理しているバージョンで実行してくれるようになります。 | 
| install | pythonのバージョンを指定してインストールできます。 | 
| uninstall | pythonのバージョンを指定してアンインストールできます。 | 
| prefix | pythonのバージョンを表示する | 
| rehash | 新しいバージョンをインストール後に実行し、pyenv shimsの更新します。 pyenv/shims/内にファイルを生成します。 | 
| root | shimsやversionsディレクトリなどが格納されているpyenvのインストール場所を表示します。 | 
| shims | pyenv用のshims(バージョン間の差異を埋めるファイル)をリスト表示する | 
| version | 現在有効なpythonのバージョンと pyenv version-fileの内容が表示される。 | 
| version-file | globalの場合は pyenv/versionとなり、localの場合はlocalを実行したディレクトリ配下に.python-versionファイルが作成されそのPATHが表示される。 | 
| version-name | 現在有効なpythonのバージョンが表示される。 | 
| versions | インストール済みのpythonのバージョン一覧と設定中のバージョンを表示する | 
| whence | 与えられた実行ファイルを含む全てのPythonのバージョンをリストアップする | 
| which | 実行ファイルのフルパスを表示する | 


Discussion