Anacondaを使った仮想環境を保存・再構築、複製

<img src="https://qiita-image-store.s3.amazonaws.com/0/212705/66ee6b1b-6c81-25d3-4529-cc9efbda445a.png" alt="仮想環境のイメージ" title="仮想環境のイメージ" width=50%>

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

今回は、Anacondaを使った仮想環境を保存・再構築、複製についてお話しようと思います。
(Anacondaに限らず、Minicondaでもcondaがインストールされているため、仮想環境を複製できると思います。)
試行錯誤した部分もあるので、分かる方いたら教えて欲しいです。

### この記事の対象者
- Anacondaで仮想環境が使える
- 仮想環境を保存しておきたい
- 同じコンピュータで仮想環境を複製したい
- 異なるコンピュータで仮想環境を再構築したい
- Anacondaのナビゲーションアプリ(マウスによる視覚的な操作)を使わず、ターミナル(コマンドによる操作)を使いたい

<!-- ### パソコンの環境
Windows 10 Pro
64ビット オペレーティング システム x64 ベース プロセッサ

Python 3.6.1 |Anaconda 4.4.0 (64-bit)| (default, May 11 2017, 13:25:24) [MSC v.1900 64 bit (AMD64)] on win32 -->

Anacondaの仮想環境の使い方を確認したい人は、[【初心者向け】Anacondaで仮想環境を作ってみる](https://qiita.com/ozaki_physics/items/985188feb92570e5b82d)を確認してください。

最初は、仮想環境の状態(インストールされているライブラリのバージョンなど)をファイルに出力して保存し、そのファイルをもとに再構築する方法を2種類紹介します。[方法1](#codna-envを使う方法)、[方法2](#condaを使う方法)
次は、ファイルに出力せず、複製する方法を紹介します。[その節へ](#仮想環境を複製ファイルに出力しない)
最後は、root環境を複製するときだけ使える方法を紹介します。[その節へ](#root環境の複製)

基本的に、保存・再構築、複製したい環境を起動して実行してください。
仮想環境の起動は以下のコマンドです。

```:ターミナル
$ source activate 仮想環境名
(Windowsならsourceは必要ない)
```

## codna envを使う方法
### 仮想環境をファイルに出力して保存
仮想環境の状態をyaml[^1]というデータ形式(拡張子は.yml)で保存します。
今いるディレクトリに保存されるので、保存したい場所に移動してから実行してください。

```:ターミナル
$ conda env export > ファイル名.yml
```
ファイルとして保存したくないけれど、もしファイルとして出力したとき、どのような内容かをターミナルで確認したい場合は下を実行してください。

```:ターミナル
$ conda env export
```

<details><summary>root環境をyamlファイルに出力しようとしたときに出たエラーと解決法</summary><div>
root環境をyamlファイルに出力しようとしたとき、以下のエラーが出ました。

```:出力
CondaEnvException: Conda Env Exception: Unable to determine environment

Please re-run this command with one of the following options:

* Provide an environment name via --name or -n
* Re-run this command inside an activated conda environment.
```
解決方法はroot環境と指定して書きます。

```:ターミナル
$ conda env export -n root > root_env.yml
```
</div></details>

### 仮想環境をファイルをもとに再構築
さきほど出力したyamlファイルをもとに仮想環境を再構築します。

```:ターミナル
$ conda env create -n 新たな環境名 -f ファイル名.yml
```
一瞬```Solving package specifications:```と出力されて、何か選択を求められているように見えることもあります。しかし、ライブラリが多くて処理が重いだけで、放置して大丈夫です。
-nを--nameに、-fを--fileにしても実行できます。

ちなみに、yamlファイル(.yml)に出力して再構築しましたが、テキストファイル(.txt)にしても正常に再構築できます。理由は分かりません。

<details><summary>root環境を再構築しようとしたときに出たエラーと解決法</summary><div>
root環境を再構築したとき、以下のエラーが出ました。

```:出力
InstallError: Error: 'conda' can only be installed into the root environment
```
解決法は出力したyamlファイルを開き、2つのライブラリを消しました。

```:yamlファイル(削除したもの)
- conda=4.3.21=py36_0
- conda-env=2.6.0=0
```
</div></details>

<details><summary>ベースのroot環境と再構築したroot環境のライブラリの違い</summary><div>
ベースのroot環境と再構築したroot環境で、それぞれ```conda list```を実行してライブラリを比較しました。すると再構築したroot環境の方に```vc:14-0```というライブラリが余分に入っていました。これが何をするライブラリなのか、よく分かりませんでした。
</div></details>

<details><summary>root環境を再構築したとき、再構築したroot環境を削除したときに出力されたエラーっぽい文</summary><div>
root環境を再構築したとき、再構築したroot環境を削除したときに出力されたエラーっぽい文を紹介します。

```:出力(root_env_ymlは自作した仮想環境)
INFO menuinst_win32:__init__(182): Menu: name: 'Anaconda${PY_VER} ${PLATFORM}', prefix: 'C:\Users\Owner\Anaconda3\envs\root_env_yml', env_name: 'root_env_yml', mode: 'None', used_mode: 'user'
```
この文はymlで再構築・削除しても、txtで再構築・削除しても出ました。
しかし、ちゃんと環境を再構築したり削除したりできたので、これが何を意味するのか分かりませんでした。
</div></details>

## condaを使う方法
### 仮想環境をファイルに出力して保存
仮想環境の状態をテキストファイル(拡張子は.txt)で保存します。
今いるディレクトリに保存されるので、保存したい場所に移動してから実行してください。

```:ターミナル
$ conda list --export > ファイル名.txt
または
$ conda list --explicit > ファイル名.txt
```
ファイルとして保存したくないけれど、もしファイルとして出力したとき、どのような内容かをターミナルで確認したい場合は下を実行してください。

```:ターミナル
$ conda list --export
または
$ conda list --explicit
```

<details><summary>--exportと--explicitの違いはライブラリの表記の違い</summary><div>
--exportと--explicitの違いは出力されるファイルでのライブラリの表記が違います。
例として\_licenseライブラリをあげます。
--exportにすると ```_license=1.1=py36_1```
--explicitにすると ```https://repo.continuum.io/pkgs/free/win-64/_license-1.1-py36_1.tar.bz2```
このように表記に違いがあるだけです。
</div></details>

### 仮想環境をファイルをもとに再構築
さきほど出力したテキストファイルをもとに仮想環境を再構築します。

```:ターミナル
$ conda create -n 環境名 -f ファイル名.txt
```
-nを--nameに、-fを--fileにしても実行できます。

<details><summary>なぜか再構築ができなかったエラーの紹介</summary><div>
私の場合、なぜか再構築ができませんでした。

```:ターミナル
$ conda create -n 環境名 -f ファイル名.txt
Fetching package metadata ...........

PackageNotFoundError: Package missing in current win-64 channels:
  - ファイル名.txt
```
</div></details>

ちなみに、テキストファイル(.txt)にして保存しましたが、yamlファイル(.yml)にしても正常に保存できます。理由は分かりません。
どちらにしても私の場合は再構築できませんでした。

## 仮想環境を複製(ファイルに出力しない)
ファイルに保存して再構築という方法ではなく、直接的に環境を複製する方法を紹介します。

```:ターミナル
$ conda create -n 新しい環境名 --clone 複製したいベースの環境名
```

<details><summary>実行した例</summary><div>

```:ターミナル(例：複製したいものpy36_base、新しい環境名test_clone)
$ conda create -n test_clone --clone py36_base
Source:      C:\Users\Owner\Anaconda3\envs\py36_base
Destination: C:\Users\Owner\Anaconda3\envs\test_clone
Packages: 8
Files: 7
#
# To activate this environment, use:
# > activate test_clone
#
# To deactivate this environment, use:
# > deactivate test_clone
#
# * for power-users using bash, you must source
#
```
</div></details>

<details><summary>root環境の直接的な複製</summary><div>
root環境も複製できそうです。複製できないライブラリが表示されますが、そのまま実行されます。

```:出力
The following packages cannot be cloned out of the root environment:
 - conda-4.3.21-py36_0
 - conda-env-2.6.0-0
 Packages: 178
 Files: 117
 (以下略)
```
しかし、root環境を複製するときも、複製したroot環境を削除したときも、以下のようなエラーっぽい文が出ました。エラーが起こりそうでオススメしません。

```:出力(test_root_cloneは自作した仮想環境)
INFO menuinst_win32:__init__(182): Menu: name: 'Anaconda${PY_VER} ${PLATFORM}', prefix: 'C:\Users\Owner\Anaconda3\envs\test_root_clone', env_name: 'test_root_clone', mode: 'None', used_mode: 'user'
```
</div></details>

## root環境の複製
root環境にある全部のライブラリを新たに作る仮想環境にインストールするというニュアンスで、root環境を複製します。

```:ターミナル
$ conda create -n 新しい環境名 anaconda
```
root環境を複製しつつ、pythonのバージョンやライブラリのバージョンを細かく指定することもできます。

```:ターミナル
$ conda create -n 新しい環境名 python=3.6 anaconda
```

どちらもanacondaと書いた部分を、他の仮想環境名にしても動作しません。


<details><summary>実行した例</summary><div>

```:出力(root_anacondaは自作した仮想環境)
Fetching package metadata ...........
Solving package specifications: .

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

The following NEW packages will be INSTALLED:

    _license:            1.1-py36_1
    (インストールするライブラリの一覧を省略)
Proceed ([y]/n)? y
INFO menuinst_win32:__init__(182): Menu: name: 'Anaconda${PY_VER} ${PLATFORM}', prefix: 'C:\Users\Owner\Anaconda3\envs\root_anaconda', env_name: 'root_anaconda', mode: 'None', used_mode: 'user'
#
# To activate this environment, use:
# > activate root_anaconda
#
# To deactivate this environment, use:
# > deactivate root_anaconda
#
# * for power-users using bash, you must source
#
```
ここでもエラーっぽい文が出力されました。しかし、複製はできるようです。

```:出力
INFO menuinst_win32:__init__(182): Menu: name: 'Anaconda${PY_VER} ${PLATFORM}', prefix: 'C:\Users\Owner\Anaconda3\envs\root_anaconda', env_name: 'root_anaconda', mode: 'None', used_mode: 'user'
```
</div></details>

<details><summary>ベースのroot環境と再構築したroot環境のライブラリの違い</summary><div>
ベースのroot環境と再構築したroot環境で、それぞれ```conda list```を実行してライブラリを比較しました。すると再構築したroot環境の方に```vc:14-0```というライブラリが余分に入っていました。これが何をするライブラリなのか、よく分かりませんでした。
</div></details>

## まとめ
ここまで読んでいただきありがとうございました。
これで仮想環境を保存・再構築、複製することができるようになりました。

しかし、まだ不明確な部分があります。
conda envで保存・再構築ができるから大丈夫といえば大丈夫ですが、condaではまったく再構築ができない問題を解決したいです。
また、root環境に関する操作でエラーっぽい文が出るのも心配です。
このように分からないけれど動くから放置している部分があるので、今後はそこを詰めていこうと思います。

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

[^1]: データ構造(リストとか数字という情報)を文字列に変換しないで保持できるデータ形式のこと。<br>JSONやCSVと同じようなもので、拡張子はymlが一般的。

## 参考文献
[Anacondaのcondaコマンドによる仮想環境の使い方のまとめ](http://minus9d.hatenablog.com/entry/2016/01/29/235916)
[conda環境の保存と再構築の仕方](https://qiita.com/nshinya/items/cb1cffabc3305c907bc5)
[Anacondaの環境をコピーする](https://qiita.com/isaac-otao/items/45d3d21b973767bd1ac1)
[公式マニュアル](https://conda.io/docs/user-guide/tasks/manage-environments.html)
[[Python]Anacondaで仮想環境を作る](https://qiita.com/supersaiakujin/items/50def6f33b79f9a61b18)


<!-- <details><summary>サンプルコード</summary><div>

</div></details> -->