Python 開発環境で virtualenv をもっと手軽に扱う vebootstrap の紹介

2018年初頭現在は Pipenv がお勧めです。
気づけば Windows 向けのバイナリを提供してくれるライブラリもかなり増えたので、(Mini|Ana)Conda を使わなくても困ることはほぼないでしょう。

----

昨今の Python 開発環境といえば下記のようなパターンが主流なのかなと思います。

* [Pythonの開発環境を構築 (pythonz, virtualenv, direnv)](http://qiita.com/jnotoya/items/ca9a0dfee6b9f084f4da)

準備が終わってしまえば柔軟な環境ができあがりますが、手順が多く python 以外のものをいろいろ導入する必要があります。また、Windows では導入が難しいものもあります。そこで、もう少し手軽にプロジェクト別の virtualenv 環境を扱えるようにする pure python なパッケージを作ってみました。

##動機

もともと理想としていたのは、セットアップが簡単で、かつ通常のスクリプト実行と同様に `python hoge.py` とするだけで、専用の virtualenv 環境がアクティブになって、必要なパッケージも入っている状態でスクリプトが起動することでした。簡単に言えばこれを実現するパッケージが今回作った `vebootstrap` になります。

vebootstrap
https://pypi.python.org/pypi/vebootstrap
https://github.com/tomoemon/vebootstrap

個人用のちょっとしたスクリプトを書く際にそこまで python のバージョンを切り替えることはないので、その点については重視していません（必要に応じて pythonz 等と組み合わせて使うことはできるはずです）。

## 動作環境

* OS
 * 下記 Python が動作する OS
 * ※Windows7, CentOS6.5 で動作確認済み
* Python
 * 2.7
 * 3.3 以降
 * ※2.7, 3.4, 3.5 で動作確認済み
* 依存パッケージ
 * [pip](http://qiita.com/takeyamajp/items/1c94048cb6f01aff5958) （最近のバージョンの python では最初からインストール済み）
 * virtualenv （`vebootstrap` 導入時に必要であれば自動的にインストールされます）

##できること

* プロジェクト（フォルダ）ごとの virtualenv 環境の分離
* python スクリプト実行時に下記の内容を自動的に処理
 * virtualenv 環境を作成、有効化
 * pip を使った依存パッケージのインストール（依存パッケージ変更時に自動更新）
 * Windows限定で、numpy や lxml, Pillow(PIL) など pip 標準でインストールできないパッケージのインストール
* 環境変数やシェルのカレントディレクトリには依存しない（実行対象のスクリプトのパスから専用の virtualenv 環境を特定する）

##できないこと

* 複数バージョンの Python の管理（パスが通っている、あるいは明示的にフルパスを指定した `python` をそのまま使います）
* virtualenv 環境の使い回し（プロジェクトごとに専用の virtualenv 環境を作る前提）

##セットアップ

利用する予定の python に対応した pip を使って vebootstrap をインストールしてください。Linux 環境でシステム標準の python を使っている場合は sudo が必要になります。

```console
$ pip install vebootstrap
```

##使い方

以下のディレクトリ名やスクリプトファイル名は適宜変更してください。ただし、`requirements.txt` は vebootstrap がその名前のファイルを探しに行くため変更しないでください。また、サンプルではプロジェクトディレクトリ内に `cd` してから実行していますが、ディレクトリ外から実行しても同様の挙動です。

※開発中のため仕様が変わる可能性があります

**もっともシンプルなパターン**

```text:ディレクトリ構成
project_test1/
    hoge.py
```

```py:hoge.py
import vebootstrap

print("Hello vebootstrap")
```

```console:コマンド実行
$ cd project_test1
$ python hoge.py
```

メインスクリプトとなる `hoge.py` の先頭に `import vebootstrap` を入れて起動すると、初回起動時に `project_test1` ディレクトリ内に　`.py##`（`##` は python バージョンが入ります）という virtualenv 環境のディレクトリを作成します。その後、その virtualenv 環境をアクティブにした状態で `hoge.py` を実行し、2回目以降の起動時はすでにある `.py##` をアクティブにして実行します。

**依存パッケージがある場合**

```text:ディレクトリ構成
project_test2/
    hoge.py
    requirements.txt
```

```py:hoge.py
import vebootstrap
import requests

print(requests.get('http://yahoo.co.jp').text[:100])
```

```text:requirements.txt
requests
```

```console:コマンド実行
$ cd project_test2
$ python hoge.py
```

`hoge.py` の初回起動時に virtualenv 環境のディレクトリを作成するのは同様で、さらに `requirements.txt` を使って依存パッケージを `pip install` します。その後、virtualenv 環境をアクティブにして `hoge.py` を実行します。`requirements.txt` を書き換えた場合は、次回起動時に virtualenv 環境を作り直します。（個別のパッケージのアンインストールが難しい場合があるのでそういう仕様にしています）

**(Windows限定) Windows 用のバイナリパッケージをインストールしたい場合**

Windows ユーザにとって `numpy` や `lxml` のように自前ビルドを要求されるパッケージのインストールはなかなか大変です。pip (PyPI) 以外の方法でビルド済みのパッケージを探して手動でインストールする必要がありますが、vebootstrap はこれを簡単にできるようにしています。

具体的には、下記サイトから対象パッケージを探してインストールするようにしています。
http://www.lfd.uci.edu/~gohlke/pythonlibs/
※個人の方が運用しているサイトのため、自己責任でのご利用をお願いします

```text:ディレクトリ構成
project_test3/
    hoge.py
    requirements.txt
```

```py:hoge.py
import vebootstrap
import numpy

print(dir(numpy))
```

```text:requirements.txt
#windows:numpy
```

```console:コマンド実行
$ cd project_test3
$ python hoge.py
```

使い方は先程までとほぼ同様ですが、`requirements.txt` の記述が少し特殊です。`#windows:hogehoge` という形式の行があると vebootstrap は先ほどのサイトから `hogehoge` パッケージを探してきます。pip にとっては `#` で始まる行はコメント扱いになるため、これは vebootstrap だけが解釈するものになります。

下記のように pip 標準でインストールするパッケージと Windows 用バイナリをインストールすることもできます。

```requirements.txt
requests
#windows:numpy
beautifulsoup4
```

どのパッケージの場合にこの特殊な書き方でビルド済みをインストールしないといけないのかどうかなんてわからん！という方は、まず最初に普通に `hogehoge` と `requirements.txt` に書いて、それでよくわからないエラーが出たら、`#windows:hogehoge` と書いてみたら良いと思います。

**関係ない import文を入れたくない場合**

`import vebootstrap` は python を実行するだけで virtualenv 環境をアクティブにするための最低限のおまじないですが、外部に公開する目的のスクリプトを作っている場合などは不要かもしれません。その場合は下記のようにモジュールをスクリプトとして実行する機能を使ってください。import 文を入れた場合と同様の挙動をします。

```text:ディレクトリ構成
project_test4/
    hoge.py
    requirements.txt
```

```py:hoge.py
import requests

print(requests.get('http://yahoo.co.jp').text[:100])
```

```text:requirements.txt
requests
```

```console:コマンド実行
$ cd project_test4
$ python -m vebootstrap hoge.py
```

**たいていのプロジェクトで使う依存パッケージを毎回書くのは面倒な場合**

頻繁にプロジェクトを作る方で毎回同じような `requirements.txt` を書いている場合は下記の機能を使ってみてください。

1度でも vebootstrap を使うと、ホームディレクトリ（Windows ユーザは `cd %USERPROFILE%`）下に `.vebootstrap` という設定ファイルが作成されます。

```json:$HOME/.vebootstrap
{
    "default_packages": [
        "ipython"
    ], 
    "default_windows_packages": []
}
```

このファイルでは、`requirements.txt` の内容によらずすべてのプロジェクトでインストールすべきパッケージを指定します。デフォルトでは該当の virtualenv 環境の REPL がすぐに使えるように `ipython` パッケージをインストールするようにしています。必要に応じて他のパッケージを追加してください。
Windows 用のバイナリについては `default_windows_packages` に `"numpy"` のような形で追加すれば、自動的にインストールされます。

いくつか追加した場合の例

```json:$HOME/.vebootstrap
{
    "default_packages": [
        "ipython",
        "requests"
    ], 
    "default_windows_packages": [
        "numpy"
    ]
}
```

##注意事項

virtualenv 環境は実行する python のバージョンごとに作られることに注意してください。下記のコマンドを打った際に、例えば `python` のバージョンが 2.7.x であれば、`.py27` という名前で virtualenv 環境を作成します（内部にコピーされる python の実行ファイルは 2.7.x のもの）。

```console
$ python hoge.py
```

さらに同じディレクトリ内で下記のコマンドを実行すると、`.py35` という名前の virtualenv 環境が作成されます。（`python3` のバージョンが 3.5.x の場合）

```console
$ python3 hoge.py
```

##さいごに

自分のメイン環境が Windows なので Linux メインな人は使いづらかったりするかもしれません。「こういうときに使えない」とかあればご指摘ください。

そして、`vebootstrap` というパッケージ名は個人的に少し長い（そしてちょっと打ちづらい）のですが、`ve` も `veb` もすでに取られてるんですよね……。

<a rel="nofollow" href="http://www.amazon.co.jp/gp/product/4048686291/ref=as_li_ss_il?ie=UTF8&camp=247&creative=7399&creativeASIN=4048686291&linkCode=as2&tag=f83wffq-22"><img border="0" src="http://ws-fe.amazon-adsystem.com/widgets/q?_encoding=UTF8&ASIN=4048686291&Format=_SL160_&ID=AsinImage&MarketPlace=JP&ServiceVersion=20070822&WS=1&tag=f83wffq-22" ></a><img src="http://ir-jp.amazon-adsystem.com/e/ir?t=f83wffq-22&l=as2&o=9&a=4048686291" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" />