【初心者向け】Anacondaで仮想環境を作ってみる

<img src="https://qiita-image-store.s3.amazonaws.com/0/212705/608a0136-c52f-644f-ca82-e80b63fcc072.png" alt="仮想環境のイメージ" title="仮想環境のイメージ" width=50%>

<span style="font-size: 120%;"><b>やっほー!　こんにちはー!</b></span>
物理好きのオザキ([@sena0801masato](https://twitter.com/sena0801masato))です。

今回は、Anacondaを使った仮想環境についてお話しようと思います。
(Anacondaに限らず、Minicondaでもcondaがインストールされているため、仮想環境を作れると思います。)

### この記事の対象者
- Anacondaをインストールしたけど使い方が分からない
- Anacondaでpythonやライブラリのバージョンを管理する機能を使いたい
- Anacondaを使うからpipではなくてcondaだけを使いたい
- Anacondaのナビゲーションアプリ(マウスによる視覚的な操作)を使わず、ターミナル(コマンドによる操作)を使いたい

分かりやすさを重視して書くため、おおよそは合っていますが厳密には違う可能性があります。
[仮想環境に関する用語](#仮想環境に関する用語)は記事の最後にまとめました。

#### 変更点
2020/06/06：見れなくなった参考ページのURLを削除しました。


## 仮想環境について
### 環境とは
環境とは、pythonのバージョン、インストールされているライブラリの種類、ライブラリのバージョンなどの状態をまとめた言い方です。

### 仮想環境とは
仮想環境とは、環境に関する概念的な単語です。
1つのパソコンの中に複数の環境を用意して、ある環境を使うときにコンピュータにはまるで、その1つの環境しかないように思わせることです。
[公式マニュアル](https://conda.io/docs/user-guide/tasks/manage-environments.html)では、conda環境と表記してありました。

仮想環境のメリットは、__複数の環境を用意できる__点です。

前提として、環境はなるべくインストールしてあるライブラリが少ない方がいいと思います。(これを環境がきれいと言うことがあります。)
なぜなら、1つの環境でアプリ開発するごとに様々なライブラリをインストールすると、使わないライブラリがインストールされていたり、いつの間にか設定が変わっていたり、同じような機能が複数存在しコンピュータがどちらを使えばいいか分からない状況が起こったりします。
すると「何が原因でエラーなのか分からない」というときがあります。(インストールしてあるライブラリが多いことを環境がきたないと言うことがあります。)
こうなったら原因を探すよりも全部アンインストールして、もう一度必要なライブラリだけインストールする方が早いです。

そこで、仮想環境を使うと複数の環境を用意できるため、アプリごとに、アプリ開発で__使うライブラリだけ入っているきれいな環境__を用意できます。
あるアプリ用の環境がきたなくなって、全部アンインストールしても、他のアプリ用の環境には何も影響がありません。
私は、自分の好きなように環境を作成したり削除したり、管理できるのが魅力だと思います。

以下で、環境を操作する方法を話していきます。

## 仮想環境を作る流れ
1. 仮想環境の確認をする
1. 使いたいライブラリが始めからAnacondaにインストールされていないか確認する
1. 使いたいライブラリのバージョンとpythonのバージョンを確認する
1. 仮想環境を作る
1. 仮想環境を起動する
1. 仮想環境にライブラリを追加する

## 1. 仮想環境の確認
Anacondaにある全部の環境が確認できます。

```:ターミナル
$ conda info -e
```
ターミナルと表記していますが、コマンドプロンプトでも同じです。
(MacOSのターミナルなら書くところの始めに\$、Windowsのコマンドプロンプトなら書くところの始めにC:(省略)>、と書いてあると思います。つまりターミナルに書く時は$を書かなくていいです。)

-eを--envsにしても実行できます。
(ハイフン2個と文字列で書くパターンは省略しない書き方で、ハイフン1個と一文字で書くパターンは省略した書き方です。)

```:出力
# conda environments:
#
root                  *  C:\Users\Owner\Anaconda3
```
環境名とディレクトリの場所が出力されます。アスタリスク(\*)のある環境が、今いる環境を示しています。
rootとはAnacondaを使うときに基礎となっている環境です。仮想環境を使わずにAnacondaを使っている人は、常にroot環境にいると思ってください。

## 2. ライブラリの確認
3つの方法を紹介します。

||確認できるか|バージョンの確認|探す手間|
|:---:|:---:|:---:|:---:|
|[方法1](#方法1検索して確認バージョンは分からない)|○|なし|なし|
|[方法2](#方法2検索して確認バージョンは分かる)|△|あり|なし|
|[方法3](#方法3一覧から探すバージョンは分かる)|○|あり|あり|

### 方法1：検索して確認(バージョンは分からない)
あるライブラリがその環境にインストールされているか検索して確認できます。
対話実行モード(REPL)にして、試しにライブラリを読み込んで(importして)確認します。

```:ターミナル
$ python
```

```:出力
(pythonのバージョンやAnacondaのバージョンが書かれる)
Type "help", "copyright", "credits" or "license" for more information.
>>>
```

```:ターミナル(対話実行モード)
>>>import ライブラリ名
```

```:出力
ライブラリがある場合
なにも表示されない(ライブラリがインストールされている)

ライブラリがない場合
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ModuleNotFoundError: No module named 'ライブラリ名'
```
以下を実行するとライブラリの保存されているファイルの場所が確認できます。

```:ターミナル(対話実行モード)
>>>ライブラリ.__file__
```

```:出力(例)
>>> datetime.__file__
'C:(省略)\Anaconda3\lib\datetime.py'
>>> numpy.__file__
'C:(省略)\Anaconda3\lib\site-packages\numpy\__init__.py'
```
### 方法2：検索して確認(バージョンは分かる)
ライブラリのバージョンまで確認したいときは、以下を実行します。
(インストールされているライブラリなのに、ライブラリがないと出力されることもあります。そういうときは[方法3](#方法3一覧から探すバージョンは分かる)で一覧から探したらバージョンが確認できると思います。)

```:ターミナル
$ python -m ライブラリ名 --version
```

```:出力
ライブラリがある場合
2.0.5　バージョンが出力される

ライブラリがない場合
No module named ライブラリ名
```
### 方法3：一覧から探す(バージョンは分かる)
環境にインストールされているライブラリの一覧を出力します。

```:ターミナル
$ conda list
または
$ conda list -n 環境名
```
-nを--nameにしても実行できます。
環境名を書かないで実行すると、今いる環境にインストールされているライブラリが出力されます。
環境名を書いて実行すると、指定した環境にインストールされているライブラリが出力されます。

```:出力(例：自作した環境名py36_Django20)
# packages in environment at C:\Users\Owner\Anaconda3\envs\py36_Django20:
#
certifi                   2016.2.28                py36_0
django                    2.0.5            py36hd476221_0   anaconda
pip                       9.0.1                    py36_1
python                    3.6.1                         2
(以下略)
```
ライブラリ名、ライブラリのバージョン、対応しているpythonのバージョンが出力されます。
(pythonのバージョンの表記法に、python3.6のときpy36と書くことがあります。)

## 3. 使いたいライブラリと対応するpythonのバージョンを確認
使いたいライブラリのバージョンと対応するpythonのバージョンを確認します。
インターネットに繋がっていないとエラーになります。

```:ターミナル
$ conda search ライブラリ名
```
検索したいライブラリ名が一部でも入っているライブラリも出力されます。
(例：numpyを検索したとき、numpydocも検索されます。)

```:ターミナル
$ conda search --full-name ライブラリ名
```
ライブラリ名が完全に一致しているライブラリを出力します。
どちらの方法でもライブラリによってはcondaに対応しているときと、していないときがあります。

```:出力(例)
condaが対応している
Fetching package metadata ...........
django                       1.7                      py27_1  defaults
                             1.7                      py33_1  defaults
                             1.7                      py34_1  defaults
                             1.7.1                    py27_0  defaults
                             1.7.1                    py33_0  defaults
(以下略)

condaが対応していない
Fetching package metadata ...........
```
condaが対応しているとき、検索したライブラリの名前(今回はDjango)、ライブラリのバージョン、対応しているpythonのバージョンが出力されます。
condaが対応していないとき、検索したことは出力されますが、対応していないため何も出力されません。

condaが対応していなかった場合は、自分でネットからライブラリの対応しているpythonのバージョンを確認してください。
参考までに、condaが対応していなかったときに私が行った[ライブラリと対応したpythonのバージョンの確認(condaが対応していない)](#ライブラリと対応したpythonのバージョンの確認condaが対応していない)を記載しました。

<details><summary>ライブラリと対応したpythonのバージョンの確認(condaが対応していない)</summary><div>
### ライブラリと対応したpythonのバージョンの確認(condaが対応していない)
私が行った、condaの対応していないライブラリで、ライブラリと対応したpythonのバージョンの確認の仕方を紹介します。
2つ方法があります。ネットで検索する方法ととりあえず環境を作る方法です。
#### ネットで検索する
1つ目は、ネットで検索してライブラリと対応したpythonのバージョンを確認します。
Anacondaで様々な[ライブラリを公開しているサイト](https://anaconda.org/)から使いたいライブラリを検索します。
ここではpygameを例に検索していきます。
<img src="https://qiita-image-store.s3.amazonaws.com/0/212705/aa8e14e9-044e-4a29-3fa3-04c3ccdffc09.png" alt="ライブラリとの対応_手順01" title="ライブラリとの対応_手順01" width=50%>

赤文字でプライベートパッケージを検索するにはログインが必要とありますが、ログインしなくても大丈夫です。
ここから自分のOSと対応していて、ダウンロード数が多いものを私は選択しました。
パッケージ名(ライブラリ名)をクリックしてFilesを選択します。
クリックするのはスラッシュの右側(pygame)です。スラッシュの両側(CogSci/pygame)をまとめてパッケージ名と命名して後で使います。
<img src="https://qiita-image-store.s3.amazonaws.com/0/212705/4528864c-3a23-1df4-5053-18b26627ab69.png" alt="ライブラリとの対応_手順02" title="ライブラリとの対応_手順02" width=50%>

一覧の中から自分のOSとライブラリのバージョン、そのあとpythonのバージョンがpyの後に書いてあります。
これでライブラリと対応したpythonのバージョンを確認できました。
<img src="https://qiita-image-store.s3.amazonaws.com/0/212705/8fedad6d-4d34-58e7-fa69-e2872714e449.png" alt="ライブラリとの対応_手順03" title="ライブラリとの対応_手順03" width=50%>

#### とりあえず環境を作る
2つ目は、とりあえず環境を作って、ライブラリをインストールしようとしたらエラーが出て、エラーを読んでpythonのバージョンを変えた環境を作り直すという方法です。
例えば、仮想環境をpython3.6で作ったが、pygameをインストールしようとしたときのエラーです。

```:出力
Fetching package metadata .............
Solving package specifications: .

UnsatisfiableError: The following specifications were found to be in conflict:
- pygame -> python 2.7* -> vc 9
- python 3.6*
Use "conda info <package>" to see the dependencies for each package.
```
これを見るとpython2.7にしたら、ちゃんとインストールできると思います。
</div></details>

## 4. 仮想環境の作成
それでは実際に仮想環境を作ってみましょう。

```:ターミナル
$ conda create -n 環境名
```
-nを--nameにしても実行できます。
これで仮想環境を作ることはできますが、pythonもインストールされていません。
たいていの場合は作成する環境にpythonをインストールするため、同時にpythonもインストールするように書きましょう。
仮想環境を削除したいときは[仮想環境の削除](#仮想環境の削除)を確認してください。

```:ターミナル
$ conda create -n 環境名 python
または
$ conda create -n 環境名 python=バージョン
```
-nを--nameにしても実行できます。
バージョンを指定しないと、condaに対応している中で最新のバージョンがインストールされます。
さきほど使いたいライブラリのバージョンと対応するpythonのバージョンを確認したので、対応するpythonのバージョンをインストールしましょう。

```:ターミナル(例)
$ conda create -n py35_pygame19 python=3.5
```
途中で、このライブラリで作成しますがいいですか?と聞かれるのでOKなときはyを入力してEnterしましょう。
始めからライブラリが自分のAnacondaにあるときはダウンロードがされませんが、ないときは自動的にダウンロードされます。たいていは何かがダウンロードされると思って大丈夫です。

<details><summary>仮想環境を作ったときの出力の例</summary><div>

```:出力(例)
Fetching package metadata ...........
Solving package specifications: .

Package plan for installation in environment C:\Users\Owner\Anaconda3\envs\py35_pygame19:

The following NEW packages will be INSTALLED:

  certifi:        2016.2.28-py35_0
  pip:            9.0.1-py35_1
  python:         3.5.4-0
  setuptools:     36.4.0-py35_1
  vc:             14-0
  vs2015_runtime: 14.0.25420-0
  wheel:          0.29.0-py35_0
  wincertstore:   0.2-py35_0

Proceed ([y]/n)? y

python-3.5.4-0 100% |###############################| Time: 0:00:02  11.15 MB/s
certifi-2016.2 100% |###############################| Time: 0:00:00  11.52 MB/s
wheel-0.29.0-p 100% |###############################| Time: 0:00:00  12.57 MB/s
wincertstore-0 100% |###############################| Time: 0:00:00   3.10 MB/s
setuptools-36. 100% |###############################| Time: 0:00:00  13.84 MB/s
pip-9.0.1-py35 100% |###############################| Time: 0:00:00  12.51 MB/s
#
# To activate this environment, use:
# > activate py35_pygame19
#
# To deactivate this environment, use:
# > deactivate py35_pygame19
#
# * for power-users using bash, you must source
#
```
</div></details>

pythonの他にライブラリも同時にインストールすることができます。
他のライブラリもバージョンを指定しなければ、pythonのバージョンに応じてインストールされます。

```:ターミナル(例)
$ conda create -n 環境名 python=3.6 numpy=1.12.1
```
また、Anacondaにインストールされている全部のライブラリを仮想環境にインストールする方法もあります。

```:ターミナル
$ conda create -n 環境名 anaconda
```
この全部のライブラリをインストールする仮想環境については、他の記事[Anacondaを使った仮想環境を保存・再構築、複製](https://qiita.com/ozaki_physics/items/13466d6d1954a0afeb3b)で詳しく紹介します。

これで仮想環境を作ることができました。
本当に作成されたか```conda info -e```で確認してみましょう。

## 5. 仮想環境の起動
仮想環境を作成するだけでは、その環境を使うことができません。
作った仮想環境を使うために起動をしましょう。

```:ターミナル
MacOSのとき
$ source activate 環境名

Windowsのとき
C:(省略)>activate 環境名
```
うまく実行されなかったり、起動したあとでpythonと書いても実行できず、対話実行モード(REPL)にならないときは、一度ターミナルを起動し直すとうまくいくことがあります。
これで仮想環境を起動して使えるようになりました。```conda info -e```でアスタリスクの位置が変わっていると思います。

起動した仮想環境を終了する場合は、ターミナルを閉じるか、以下を実行してください。

```:ターミナル
MacOSのとき
$ source deactivate

Windowsのとき
C:(省略)>deactivate
```
(私のコンピュータではdeactivateするとターミナルを閉じるまでpythonを認識してくれず、対話実行モード(REPL)にならなくなるので、ターミナルを閉じるようにしています。)

## 6. 仮想環境にライブラリを追加
Anacondaを使う人は、ライブラリをインストールするときに、pipを使うパターンとcondaを使うパターンがあります。記事の最後に[pipとcondaの違い](#仮想環境に関する用語)を書きました。

Anacondaでは、pipを使うとエラーになることがあるという[記事01](http://onoz000.hatenablog.com/entry/2018/02/11/142347)を見かけたため、condaだけを使うようにしました。
おかげで少し面倒な方法をとることもありますが、エラーで困るよりいいと思います。

仮想環境にライブラリを追加する方法は主に2種類あります。
condaが対応している場合と対応していない場合です。

まず、condaが対応しているか確認するためにライブラリを検索します。
([3. 使いたいライブラリと対応するpythonのバージョンを確認](#3-使いたいライブラリと対応するpythonのバージョンを確認)で使ったコマンドと同じです。)

```:ターミナル
$ conda search ライブラリ名
```
ここで、インストールしたいライブラリのバージョンがあればcondaが対応しています。
condaが対応していても、インストールしたいバージョンが無かったら、condaが対応していない場合と同じようにインストールしてください。

### 1. ライブラリのインストール(condaが対応している)
condaが対応している場合、以下を実行するだけです。
その仮想環境にインストールされているpythonに合わせて、ライブラリをインストールしてくれます。

```:ターミナル
$ conda install ライブラリ名
```
これでライブラリをインストールできました。```conda list```で確認してみましょう。

### 2. ライブラリのインストール(condaが対応していない)
condaが対応していない場合、3つの手順があります。

1. パッケージ名(ライブラリ名)を決定する
1. インストールしたいパッケージ名(ライブラリ名)のURLを調べる
1. インストールする

一つずつ紹介していきます。

#### 1. パッケージ名(ライブラリ名)を決定する
同じ名前のライブラリでも様々な種類があるので、どれを使うか検索して決定します。

```:ターミナル
$ anaconda search -t conda ライブラリ名
```
-tを--package-typeにしても実行できます。
ここではpygameを例にします。

```:出力
Using Anaconda API: https://api.anaconda.org
Run 'anaconda show <USER/PACKAGE>' to get more details:
Packages:
     Name                      |  Version | Package Types   | Platforms
     ------------------------- |   ------ | --------------- | ---------------
     CogSci/pygame             |  1.9.2a0 | conda           | linux-64, win-32, osx-64, win-64
                                          : Python library based on SDL for making games
     Maceo57/pygame            |  1.9.2a0 | conda           | osx-64
     auto/pygamess             |    0.3.0 | conda           | linux-64
                                          : https://github.com/kzfm/pygamess
(以下略)
```
[使いたいライブラリと対応するpythonのバージョンを確認(condaが対応していない)](#ライブラリと対応したpythonのバージョンの確認condaが対応していない)で調べたパッケージ名(ライブラリ名)を使ってください。

#### 2. インストールしたいパッケージ名(ライブラリ名)のURLを調べる
インストールしたいパッケージ名(ライブラリ名)の詳細を見て、インストールに使うURLを調べます。

```:ターミナル
$ anaconda show パッケージ名(CogSci/pygameなど)
```

```:出力
Using Anaconda API: https://api.anaconda.org
Name:    pygame
Summary: Python library based on SDL for making games
Access:  public
Package Types:  conda
Versions:
   + 1.9.2a0

To install this package with conda run:
     conda install --channel https://conda.anaconda.org/CogSci pygame
```
出力の最後に書いてあるURLを使います。
(最後1行をそのままコピー貼り付けして使ってもいいです。)
#### 3. インストールする

```:ターミナル
$ conda install -c 調べたURL パッケージ名
```

```:ターミナル(例)
$ conda install -c https://conda.anaconda.org/CogSci pygame
```
-cを--channelにしても実行できます。(つまり最後の一行と同じ)
これでライブラリをインストールできました。```conda list```で確認してみましょう。

## 仮想環境の削除

```:ターミナル
$ conda remove -n 環境名 --all
```
-nを--nameにしても実行できます。


## まとめ
ここまで読んでいただきありがとうございました。
これで仮想環境を作る、起動する、ライブラリを追加することができるようになりました。
ぜひアプリごとに仮想環境を使い分けるなど、使ってみてください。

この他にもAnacondaの機能として仮想環境を保存・再構築、つまり環境ごとコピーして複製することができます。その方法は他の記事[Anacondaを使った仮想環境を保存・再構築、複製](https://qiita.com/ozaki_physics/items/13466d6d1954a0afeb3b)で書きます。

個人的には、Anacondaをインストールしたけど、使うのが仮想環境だけならMinicondaでもよかったかなぁと思います。
Anacondaにはpythonに特化したエディタ(Spyder)など含まれていることが魅力だと思うので、積極的に使っていこうと思います。

<span style="font-size: 120%;"><b>ではでは!</b></span>

## 参考文献
[【初心者向け】プログラミングを始める2つの手順](http://othlotech.hatenablog.com/entry/2018/03/03/162432)
[venv: Python 仮想環境管理](https://qiita.com/fiftystorm36/items/b2fd47cf32c7694adc2e)
[condaとpip：混ぜるな危険](http://onoz000.hatenablog.com/entry/2018/02/11/142347)
[Anaconda で Python 環境をインストールする](https://qiita.com/t2y/items/2a3eb58103e85d8064b6)
[Anaconda - Python.jp](https://www.python.jp/install/windows/anaconda/install_anaconda.html)
[[Python]Anacondaで仮想環境を作る](#https://qiita.com/supersaiakujin/items/50def6f33b79f9a61b18)
[[備忘] python / conda環境構築の基本コマンド一覧](#https://qiita.com/yampy/items/4e89cd97179bbd20f726)
[公式マニュアル](#https://conda.io/docs/user-guide/tasks/manage-environments.html)

## 仮想環境に関する用語
- <b>ライブラリ</b>
ライブラリとは、便利なプログラムが使いやすいようにまとまっているものです。
厳密にはモジュールと言ったりパッケージと言ったりしますが、だいたい同じような意味と認識して大丈夫です。
基本的には、自分の使いたい機能が入っているライブラリをネットで探して、インストールして使います。例えば、数学の高度な式を扱うnumpy、グラフを表示するmatplotlib、webアプリの土台となるdjangoなどがあります。
しかし、pythonでは使うことの多いライブラリが始めからインストールされています。それらを標準ライブラリといいます。例えば、日時を扱うdatetime、数学の簡単な式を扱うmath、ランダムな値を生成するrandomなどがあります。

- <b>Anaconda</b>
Anacondaとは公式のPythonと科学でよく使うライブラリが一緒になったものです。
Anacondaをインストールするだけで、Pythonと標準ライブラリと科学系のライブラリが使えるようになります。

- <b>pipとcondaの違い</b>
どちらもライブラリを管理するシステムとしては同じです。
pipはPython3.4から標準ライブラリとなりました。pipは環境まで管理する機能はなく、ライブラリのインストール、アンインストール、アップデートができます。
condaを使わずに環境を管理する方法としてライブラリのvenvがありますが、venvでもpythonのバージョンまで管理することはできません。(pyenvはpythonのバージョンも管理できますが、近年では非推奨になっています。)
せっかくAnacondaをインストールしているならcondaを使ってバージョン管理しましょう。

<!-- 「場合」は条件の中身が大きいときに使われ、「とき」は条件が小さいときに使われる -->