【2021-06-15 更新】本記事の内容は時代遅れです。 pyenvでPythonのバージョン、 poetryでパッケージと依存関係を管理するのが良いと思います。 「2021 python パッケージ管理」で検索すると 2021現在で最適な方法が得られます。

プログラミングを学んだことのある人は(というより開発経験のある人は?) 仮想環境について馴染みがあるかもしれないのですが、 僕みたいな文系人間だと 「そもそも仮想環境ってなんですか」という話になるので、 まずはメリットから考えてみましょう。

仮想環境には2つの軸があって、 PythonやRといったアプリケーションのバージョンを仮想的に用意してあげるもの(pyenv)と、 アプリケーション内でつかうライブラリのバージョンを仮想的に用意してあげるもの(venv)が有ります。 これらの仮想環境のおかげで、研究/開発でのバージョンが合わない事故を事前に防げるので 再現性を求められる状況では必須になります。 (ナウいやり方は Docker とか Poetry とかだと思うのですが、ちょっと保留)。

かく言う自分もはじめの頃は Pythonに numpy とか PIL とかのライブラリーを導入する際は pip install ばかりしていました。 お手軽にライブラリーを組み込めるのは便利でよろしいのですが、 「他の端末でも同じ環境を作ろう!」となった段階で どのライブラリーが必要なのか分からなくなってしまったので1、 慣れてきたら早いうちに環境は明示的にしておいた方が良いのかなと思います。

その時に知ったのが仮想環境で、Pythonと仲良くする第一歩なんじゃないかなと思います。

環境を透明にして再現性が欲しい

そもそも仮想環境を立てると何が嬉しいの? という話です。 環境をクリーンに保てば import できるモジュールと import できないモジュールを分離でき、 コードを共有する段階で「どのモジュールが必要だったっけ」 状態を回避できます 2

実例としてはMeCabなんかが良い例で、 OSの違いも加わって夏の数時間が溶けた記憶があります。 結局、WindowsにMeCab入れるよりWindowsにLinux入れるほうが早い3 という意味不明な結果になりました。

もちろん「この環境を使うのは自分だけだし」と思うのはもっともなのですが、 しかし将来の自分が同じ環境を使い続けるとも、 同じPCを使っているとも限りませんよね (必要なライブラリが違うパッケージ、Pythonのバージョンを要求することは割とある)。 そういう意味でも仮想環境がオススメなのです。

実際に仮想環境をvenvで作ってみる

じゃあどうすれば、という話ですが、 まず Python3 (正確には3.3以上)を使っている人はvenvを使うのがよさ気です。 ネットには pyvenv やら何やらが使われている情報がありますが、 公式は以下の様に述べております。 適宜公式にないとだめですね。 なお、ややこしいですが Pythonのバージョン指定には pyenv が使いやすい印象です。

pyvenv スクリプトは Python 3.6 で非推奨となり、 代わりに python3 -m venv を使い、 仮想環境を動かす Python インタープリタを取り違える可能性を防ぎやすくします。

次に まずは pip があるかを確認してみます。 これはpip --versionで確かめられます。もし導入されていない場合は大抵、 どうすれば導入できるのかを指示してもらえます。 例えば、 Debian/Ubuntu systems では apt-get install python3-venv しろー、と言ってもらえます。

pipがある状態ならもう仮想環境はつくれます。 例えば、今回はnpiという現象を分析をするのでnpiという環境名にします。 名前も決まったところで開発、研究を行うディレクトリで、以下のコマンドを実行します。 ./ 以下に先ほど決めた名前があることが分かると思います。

python3 -m venv ./npi/

Git使っている人は作成された仮想環境をトラックしないようGitに指示します。

echo /npi/* >> .gitignore

仮想環境を使ってみる

ここまで来たら後は仮想環境を起こしたり寝かしたりするだけです。 起こし方と寝かし方は、それぞれ以下の通りです。 余裕のあるひとは .bashrc とかに alias 貼っておくと便利です。

#「npi/bin/にある`activate`という命令を`source`で実行してください」という意味です。
# サイトによっては`source`の代わりにピリオド一つだったりします。
source npi/bin/activate
# 寝かします
deactivate npi

上のコマンドを実行すると、 ターミナルのプロンプト部分の左側にカッコで仮想環境の名前が出たり 隠れたりします。

kishiyama:~/home/lecture/find-npi (master=) $ source npi/bin/activate
(npi) kishiyama:~/home/lecture/find-npi (master=) $ deactivate npi
kishiyama:~/home/lecture/find-npi (master=) $ 

この括弧内に仮想環境名が出ている状態でpipします。 すると仮想環境内にモジュールがダウンロードされます。

裏を返せば、仮想環境をdeactivateで抜ければ 仮想環境内のモジュールにはアクセスできなくなります。 つまり、仮想環境は使うモジュールの種類と管理を 指定できる、ということですね。

以上で仮想環境の立て方は終わりです。 変に立ててしまった場合は rm -rf で消してます (-fオプション付いているので本当に注意して実行してください!)。 これでpipを存分に明示的に使えます。

ちなみに環境にあるパッケージはは以下のコマンドで取得して requirement.txt なんかに入れらます。

pip freeze > requirements.txt

以下のコマンドで保存した requirements.txt を読み込めます。

pip install -r requirements.txt

これで明示的な仮想環境構築はバッチリですね。

まとめ

明示的にモジュールの書き出し、読み込みを行ないたいです。


  1. pip freeze(ライブラリーの一覧取得)をして見知らぬ大量のモジュールが吐き出された苦い経験があります。 

  2. 環境ごとにコードの挙動が変わってしまうと頭が痛くなります。 例えばPythonのバージョンの違い(2 or 3)だけでも挙動が違うのに、 実際はモジュールのバージョンの違いも挙動の差に貢献してしまうワケですね。 

  3. 教授に話したら「うん、そうだよね」と共感をいただけた。