dackdive's blog

新米webエンジニアによる技術ブログ。JavaScript(React), Salesforce, Python など

[Python]pyenvとvirtualenvとpyenv-virtualenv

pyenv とか virtualenv を使いだしてだいぶ経つけど、メモ。
web 上の記事で、virtualenv と呼んでいるものが実は pyenv-virtualenv のことだった、というのがたびたびあって
しばらく自分も勘違いしてました。

結局、最初に pyenv とか virtualenv の使い方を学ぶ時に参考にした
こちらのサイトが一番わかりやすく、正確でした。

http://blog.ieknir.com/blog/pyenv-with-virtualenv/


pyenv

https://github.com/yyuu/pyenv

  • 1台のPC内で 異なるバージョンの Python を管理する ためのツール
  • インストールは mac の場合 Homebrew から行うことができる
$ brew install pyenv

サンプル

$ pyenv versions
* 2.7.10 (set by /Users/yama/.pyenv/version)

# 異なるバージョンのPythonをインストール
$ pyenv install 2.7.5
$ pyenv install 3.3.6
$ pyenv versions
* 2.7.10 (set by /Users/yama/.pyenv/version)
  2.7.5
  3.3.6

# バージョンの切り替え
$ pyenv global 3.3.6
$ python --version
Python 3.3.6

# 特定のディレクトリ以下でのみバージョンを切り替え
$ pwd
/Users/yama/workspace
$ mkdir pyenv-sandbox
$ cd pyenv-sandbox
$ pyenv local 2.7.5
$ ls -a  
./               ../              .python-version  # .python-version というファイルが作られる
$ python --version
Python 2.7.5
$ cd ..
$ python --version
Python 3.3.6  # ディレクトリを抜けると global の設定が適用される


virtualenv

https://virtualenv.readthedocs.org/en/latest/

  • 同一バージョンの異なる Python 環境(仮想環境、などと呼ぶ)を管理する ためのツール
  • pyenv とは無関係
  • Python のパッケージ なのでインストールは pip などを使って行う
$ pip install virtualenv

サンプル

# 現在の Python 環境
$ python --version
Python 3.3.6
$ pip list
pip (7.1.2)
setuptools (18.7.1)
virtualenv (13.1.2)
wheel (0.26.0)

$ pwd
/Users/yama/workspace
$ mkdir virtualenv-sandbox
$ cd virtualenv-sandbox

# 仮想環境 "django" を作成する
$ virtualenv django
$ ls
django/
# 仮想環境 "django" を有効化 (activate)
$ source django/bin/activate
(django) $   # ← 現在 activate されている仮想環境名が表示される
(django) $ pip list
pip (7.1.2)
setuptools (18.2)
wheel (0.24.0)

(django) $ pip install django==1.8
(django) $ pip list
Django (1.8)
pip (7.1.2)
setuptools (18.2)
wheel (0.24.0)

# 仮想環境を無効にすると、元の環境には Django はインストールされていない
(django) $ deactivate
$ pip list
pip (7.1.2)
setuptools (18.7.1)
virtualenv (13.1.2)
wheel (0.26.0)


pyenv-virtualenv

https://github.com/yyuu/pyenv-virtualenv

これの説明は、冒頭でも紹介したこちらのサイトの説明が一番わかりやすかったです。
http://blog.ieknir.com/blog/pyenv-with-virtualenv/

pyenv-virtualenvはpyenvのPython環境の名前空間が従来はバージョン番号のみだったのに対し任意の文字列を利用することが可能になるpyenvプラグイン

  • つまり pyenv をより便利に使用するためのもの、という位置づけ
  • virtualenv と名前がついてるが↑の virtualenv とは直接の関係はない
    • 同じような機能を提供しているけど内部で使っているとかではないと思う。※未確認
  • pyenv と同じ作者
  • インストールは pyenv 同様 Homebrew から
$ brew install pyenv-virtualenv


サンプル

# 例) 同じ Python 3.3.6 で、
# Django を入れた環境と Flask を入れた環境を別々に用意したい
$ pyenv versions
  2.7.10
  2.7.5
* 3.3.6 (set by /Users/yama/.pyenv/version)

# 仮想環境を作成する.
# 基本は `pyenv virtualenv [バージョン] [仮想環境名]` で良く
# [バージョン] を省略すると現在のバージョンが使われる.

# Django を入れる用の仮想環境
$ pyenv virtualenv py3.3-django
$ pyenv versions
  2.7.10
  2.7.5
* 3.3.6 (set by /Users/yama/.pyenv/version)
  py3.3-django

# Flask を入れる用の仮想環境
$ pyenv virtualenv py3.3-flask
$ pyenv versions
  2.7.10
  2.7.5
* 3.3.6 (set by /Users/yama/.pyenv/version)
  py3.3-django
  py3.3-flask

# `pyenv virtualenvs` で仮想環境だけ表示することも可能
$ pyenv virtualenvs
  py3.3-django (created from /Users/yama/.pyenv/versions/3.3.6)
  py3.3-flask (created from /Users/yama/.pyenv/versions/3.3.6)
 
# それぞれの環境にパッケージをインストールしてみる
$ pyenv global py3.3-django
$ pip list
pip (7.1.2)
setuptools (18.2)
wheel (0.24.0)

$ pip install django
$ pip list
Django (1.9)
pip (7.1.2)
setuptools (18.2)
wheel (0.24.0)


$ pyenv global py3.3-flask
pip (7.1.2)
setuptools (18.2)
wheel (0.24.0)

$ pip install flask
$ pip list
Flask (0.10.1)
itsdangerous (0.24)
Jinja2 (2.8)
MarkupSafe (0.23)
pip (7.1.2)
setuptools (18.2)
Werkzeug (0.11.2)
wheel (0.24.0)

# 仮想環境の削除
$ pyenv uninstall py3.3-flask
pyenv: remove /Users/yama/.pyenv/versions/py3.3-flask? yes
$ pyenv virtualenvs
  py3.3-django (created from /Users/yama/.pyenv/versions/3.3.6)

(2016/02/12追記)
こっちのサンプルには書いてませんでしたが pyenv-virtualenv も pyenv local が使えます。
(追記ここまで)


virtualenv と pyenv-virtualenv、どちらを使うべき?

両者の使い方をふまえてユースケースに合ったものを選びましょう。

たとえば、Heroku アプリケーションを作る場合はアプリケーションディレクトリごとに独立した仮想環境があった方がいいので
virtualenv を使うのがいいと思います。
pyenv global でどこでも切り替えられるメリットがないし、アプリごとに違う名前つけないといけないので。

実際、公式チュートリアル でも virtualenv をインストールするように書かれてますね。

(2016/02/12追記)
意図が非常に伝わりづらい書き方をしていたので補足です。
たとえば、このような感じです。

# 先ほど作成した Django インストール済みの仮想環境があるとする
$ pyenv global py3.3-django
$ pip list
Django (1.9)
pip (7.1.2)
setuptools (18.2)
wheel (0.24.0)

$ cd ~/workspace

### Heroku アプリケーション `app1` を開発する ###
# Heroku 用のテンプレートからアプリのひな形を作成する
# (参考: http://dackdive.hateblo.jp/entry/2015/12/22/110707)
$ django-admin.py startproject --template=https://github.com/heroku/heroku-django-template/archive/master.zip --name=Procfile app1
$ cd app1

# このアプリケーションのためだけの仮想環境を作り、有効化
$ virtualenv venv
$ source venv/bin/activate
(venv) $

# Django 必要になるのでインストール
(venv) $ pip install django

# さらに、このアプリケーションでは `package1` というパッケージを使うのでインストール
(venv) $ pip install package1
(venv) $ pip list
Django (1.9)
package1 (1.0)
pip (7.1.2)
setuptools (18.2)
wheel (0.24.0)


### また別のアプリケーション `app2` を開発する ###
(venv) $ deactivate
$ cd ..
$ django-admin.py startproject --template=https://github.com/heroku/heroku-django-template/archive/master.zip --name=Procfile app2
$ cd app2
# ここでも仮想環境を用意
$ virtualenv venv
$ source venv/bin/activate
(venv) $

# こっちでは `package2` というパッケージを使う
(venv) $ pip install package2
(venv) $ pip list
Django (1.9)
package2 (1.0)
pip (7.1.2)
setuptools (18.2)
wheel (0.24.0)

# 元々使用していた py3.3-django には変化なし
(venv) $ deactivate
$ pip list
Django (1.9)
pip (7.1.2)
setuptools (18.2)
wheel (0.24.0)

この例において、アプリケーション app1app2 はともに Python3.3.6 と Django1.9 という組み合わせなので
別にアプリケーションごとに仮想環境を用意する必要はなさそうに思えますが、
そうすると py3.3-djangopackage1package2 を両方インストールすることになり
それぞれのアプリケーションをローカルで開発するにあたって、本番環境ではインストールされないパッケージを含んだ状態で開発をすることになります。
それを避けるために、アプリケーション単位で仮想環境は用意すべきだと考えます。

また、以下のように各アプリケーションで使用するための仮想環境を pyenv-virtualenv で用意することも可能です。

$ pyenv virtualenv 3.3.6 app1
$ pyenv versions
  2.7.10
  2.7.5
* 3.3.6 (set by /Users/yama/.pyenv/version)
  app1
  py3.3-django


# `app1` ディレクトリでのみ仮想環境 `app1` を有効にする
$ cd ~/workspace/app1
$ pyenv local app1
$ pyenv versions
  2.7.10
  2.7.5
  3.3.6
* app1 (set by /Users/yama/.pyenv/version)
  py3.3-django

$ ... # この状態で `app1` に必要なパッケージをインストールする

ですが、このようにして作成した仮想環境 app1 は別のところで再利用することがほとんどないと考えられるため、このようなケースでは virtualenv が適しているのでは、という話でした。
(追記ここまで)


(おまけ) pyenv-virtualenvwrapper

https://github.com/yyuu/pyenv-virtualenvwrapper

こちらについては使ったことがないので詳しくはわかりませんが、README.md の冒頭には

An alternative approach to manage virtualenvs from pyenv.

とあるので、pyenv-virtualenv と同じようなことを実現するための別の pyenv プラグインという感じがします。

  • pyenv, pyenv-virtualenv と同じ作者
  • 元々 virtualenv を使いやすくするための virtualenvwrapper という Python パッケージがあり、それに関係?
  • virtualenvwrapper も使ったこと無い。。。