Anacondaと付き合うための情報を整理する（Pythonのインストール方法とパッケージ管理方法を中心に）

## はじめに

PyCon JP 2019で「Anaconda環境運用TIPS」という15分のトークをします。
ドキュメントを当たったり、Anacondaの環境で実験したりして得た知見全てを15分のトークに収めることが難しかったので、別途記事にすることにしました。
正確性を重視したいので、誤った記載を見つけた場合は、コメントなどでご指摘いただけるとありがたいです。

##前提

### この記事で扱うこと

- Pythonのインストール方法（Anaconda中心）
- AnacondaでPythonをインストールした場合のパッケージ管理方法の特徴

### 扱わないこと

- パッケージとは
- Anacondaの環境（base環境とは）
- condaコマンドの詳細な使い方（特に環境を分離する方法）

今後の更新や別記事でアップデート予定です。

### おことわり

この記事を書く意図は、Anacondaをオススメすることでは**ありません**。
自分の中に蓄積されたAnacondaに関係する情報の整理が目的です。

また、書き手はPythonを使った開発で**Anacondaを使っているわけではありません**。
Pythonを教える中で、Anaconda環境の問題を何件か解決し、この記事に記載した認識に至りました。
（誤りがあるかもしれませんので、お気づきの点はお知らせください）

### 動作確認環境

- macOS 10.12.6
- conda 4.6.11

一部の検証にDockerイメージも使っています。

## Pythonのインストール方法

Pythonには複数のインストール方法があります。
どういった方法があり、それぞれどのくらいの人が使っているかは、例えば、JetBrainsが調査した[Python Developers Survey 2018 Results](https://www.jetbrains.com/research/python-developers-survey-2018/)があります（Python Installation and Upgradeという項目[^1]）。

- 1位はOSごとに提供される方法（`apt-get`, `yum`, `brew`など）で38%
- 2位は[Python.org](https://www.python.org/)で33%
- 3位がAnacondaで22%

[^1]: %の合計が100を超えるので、複数回答と考えています

また、2019年4月に「みんなのPython勉強会」で環境構築について話した際に参加者に挙手していただいたところ、AnacondaでPythonをインストールした方が半数で、Python.orgからインストールした方よりも多かったと記憶しています。

というわけで、ここでは、**Pythonをインストールする際に、Anacondaという選択肢を選ぶ人が増えている**ことを確認しました。[^2]

[^2]: この理由について、JetBrainsの調査は「Pythonを使う他の種類の開発よりもデータサイエンスの人気が増していることを示している」と述べています。また、私の推測ですが、国内では毎月のように機械学習の入門書（やPythonの入門書）が刊行されており、そこでAnacondaが紹介されることが多いという理由もありそうです。後の節で触れますが、インストールする手順が簡単というのは著者にとって魅力なのでしょう。

## AnacondaでPythonをインストールする際の特徴

では、AnacondaでPythonをインストールした場合、他の方法と何が違うのでしょうか。
大きな特徴は、Pythonをインストールするだけでなく、**科学計算に使うパッケージも合わせてインストールする**[^3]ということです。
Python.orgや`brew`や`apt`でPythonをインストールする場合、科学計算に使うパッケージを別途インストールする必要があります。

[^3]: https://docs.python.org/ja/3/using/windows.html#alternative-bundles

科学計算に使うパッケージ（numpy, scipy, pandas）が合わせてインストールされている例を見てみましょう。
AnacondaをインストールしたmacOSのターミナルでPythonを対話モードで起動します。

```
(base) $ python
Python 3.7.3 (default, Mar 27 2019, 16:54:48) 
[Clang 4.0.1 (tags/RELEASE_401/final)] :: Anaconda, Inc. on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import numpy, scipy, pandas
>>> 
```

科学計算のパッケージに関連して、Anacondaでは機械学習のパッケージ（例：tensorflow）もインストールしやすいという特徴があります。
（macOSやLinuxを使った経験では、Python.orgからインストールしたPythonでも環境構築できました。私が未経験のWindowsでは苦労があるのかもしれません）

他の特徴として、Anacondaはクロスプラットフォームであり、Windows・macOS・Linuxいずれでも動作する[^4]という点も挙げられます。
これは`brew`や`apt`などOSごとに提供される方法でPythonをインストールする選択肢とは対照的ですね。

[^4]: https://packaging.python.org/guides/installing-scientific-packages/#the-conda-cross-platform-package-manager

## `conda`コマンド

Anacondaにおけるパッケージ管理は`conda`というコマンドで行われます。
AnacondaにおいてはPythonもパッケージとして扱われるため、Pythonのバージョンも管理[^5]できます（脚注4のリンク参照）。

[^5]: Pythonのバージョン管理は後述の`pip`ではできません

AnacondaでPythonを導入するとbaseという名前の環境ができます。
そこに含まれるパッケージの一覧を`conda list`で表示してみましょう。

```
(base) $ conda list
# Name                    Version                   Build  Channel

numpy                     1.16.2           py37hacdab7b_0  

pandas                    0.24.2           py37h0a44026_0  

python                    3.7.3                h359304d_0  

scipy                     1.2.1            py37h1410ff5_0  
```

200行を超える出力があるため、上では一部を抜粋しました。
AnacondaでPythonをインストールすると、200を超えるパッケージもすぐに使える状態というわけです。

Anacondaを使わずにPythonをインストールした場合、`conda`コマンドは使えず、`pip`というコマンドでパッケージを管理します。
混乱を招きやすいのですが、`pip`コマンドはAnacondaでも使うことができます（この点については理解して使っていただきたいため、詳細を後述します）

|      | `conda` | `pip` |
| ---- | ---- | ---- |
| Anaconda | ◯（オススメしたい） | △（使える） |
| Anaconda以外 | ☓（使えない） | ◯（オススメしたい） |

## なぜAnacondaが登場したか

Anacondaが登場した背景として、科学計算に用いるパッケージにはバイナリモジュールに依存するものがあり、`pip`コマンドでインストールすることが難しい[^6]ことがあったそうです。
このあたりの状況は改善してきている[^7]と認識していますが、科学計算のパッケージのインストールのしにくさという問題により、今後もAnacondaは1つの選択肢として残り続けるのではないかと私自身は考えています。

[^6]: https://docs.python.org/ja/3/installing/index.html#install-scientific-python-packages
[^7]: numpy 1.10.4やscipy1.0.0以降はメジャーなOS向けにwheelフォーマットでパッケージがリリースされているそうですが、Windowsでは最適化された線形代数演算の性能が出ない可能性があるそうです ref:https://packaging.python.org/guides/installing-scientific-packages/ 

## `conda`と`pip`の違い

上では`conda`ではPythonのバージョンを管理できるが、`pip`ではできないという違いを見ました。
実はこの点よりも重要な違いがあります。
それは、**配布されたパッケージをインストールする際の参照先のサイト（リポジトリ）**が異なるということです。

`conda`でも`pip`でも、配布されたパッケージ（アーカイブされたファイル）をインターネット経由でダウンロードし、手元の環境にインストールします[^8]。

[^8]: [Distribution Packageの用語説明](https://packaging.python.org/glossary/#term-distribution-package)をもとにしています

`pip`でパッケージをインストールする場合は、デフォルトで[PyPI](https://pypi.org/)（Python Package Index）にあるパッケージを参照します。
一方、`conda`でパッケージをインストールする場合、デフォルトではAnaconda社が管理するリポジトリ（repo.anaconda.com）を参照します[^10]。

[^9]: https://docs.python.org/ja/3/installing/index.html#key-terms
[^10]: https://conda.io/en/latest/

PyPIは開発者に公開されており、誰でもPythonのパッケージを配布するために利用できます。
そのため、大量の多岐に渡るパッケージが集まっています。

一方、Anaconda社のリポジトリは、開発者に公開されているわけではありません。
Anaconda社が管理しているため、PyPIに比べてパッケージはずっと少ないです。
また、PyPIにある最新版が必ずあるとは限りません。
この点への対応として、コミュニティが運営する[conda-forge](https://conda-forge.org/)などのリポジトリから`conda`コマンドでパッケージをインストールする方法が案内されています[^11]。

[^11]: https://docs.conda.io/projects/conda/en/latest/user-guide/concepts/channels.html （ドキュメント上ではリポジトリのことをチャンネルと呼んでいるようです）

ここまで、`conda`の場合も`pip`の場合もパッケージという同じ言葉を使ってきましたが、実は`conda`と`pip`とでパッケージの形式は異なります[^14]。

[^14]: ref: [`conda`で扱うパッケージ](https://docs.conda.io/projects/conda/en/latest/user-guide/concepts/packages.html#what-is-a-conda-package)、[`pip`で扱うパッケージ](https://packaging.python.org/tutorials/packaging-projects/)

## `conda`と`pip`は混ぜられる？

Anacondaは導入がしやすい反面、**パッケージのリポジトリという点でやや苦労するという印象**を私は持っています。
対応として、conda-forgeを紹介しましたが、`conda`コマンドのドキュメントでは、conda-forgeで対応できない場合、`pip`を
使うことが案内されています[^12]。

[^12]: https://docs.conda.io/projects/conda/en/latest/user-guide/concepts/channels.html#conda-channels

この記載を見て、「[condaとpip：混ぜるな危険](http://onoz000.hatenablog.com/entry/2018/02/11/142347)」という2018年2月のエントリを思い出す方もいるでしょう。
「`conda`と`pip`を混ぜていいの？」と。

ドキュメントの記載によれば、`conda`の4.6以降では`conda`と`pip`が混ぜられる[^13]ようです。
しかしながら、環境によっては壊れてしまうこともあるようなので、この記事の初公開の段階では積極的にオススメはしません。
（このあたり登壇当日までに結論を出し、アップデートします）

> （前略） conda now understands pip metadata more intelligently.

（注）リンク先には以下の2つが記載されており、ここで紹介しているのは後者の方です。

- experimentalな機能：`.condarc`（`conda`の設定ファイルの編集） 
- `conda`が`pip`のメタデータに対応した話

後述の実験結果から、後者の機能はexperimentalの機能とは別に有効になっていると考えています。

（注 終わり）

[^13]: https://docs.conda.io/projects/conda/en/latest/user-guide/configuration/pip-interoperability.html

Dockerイメージ[continuumio/anaconda3](https://hub.docker.com/r/continuumio/anaconda3)のタグ2019.07を用いて実験してみました。

1. base環境に入っていないtensorflowのバージョン1.13.1を`conda install tensorflow=1.13.1`でインストール
2. `pip install -U tensorflow`で最新のバージョン1.14.0にアップデート
3. 対話モードやJuputer Notebookでtensorflowがimportできることを確認

Dockerイメージを用いた検証では、無事importできました。
しかしながら、macOSにてbaseと同様の環境を作って検証をしたところ、3に失敗する結果となりました。
（「Illegal instruction: 4」と表示されて対話モードが終了します。JuputerではKernelがRestartします）

ドキュメント上は`conda`と`pip`が混ぜられると記載されていますが、**混ぜることで環境を壊さない可能性が絶対にないとは言えないという認識**でいます。
そこで、Anacondaを使っている場合のパッケージ管理（暫定版）は

1. まずAnaconda社のリポジトリやconda-forgeを検索
2. 1で見つからない場合は、リスク承知でPyPIからインストール

という手順になりそうです。
そして、Anaconda社のリポジトリやconda-forgeからインストールしたパッケージのアップデートは`conda`コマンドを使うことで、環境を壊すリスクは低減されると考えています。

環境が壊れるリスクを抑える別の方法としては、**Anacondaの環境を開発ごとに分離して使う**ことを私はオススメしたいです。
分離してあれば、ある環境が壊れたとしてもAnaconda自体の再インストールは発生しないと考えています。

Anacondaを使った場合の環境の切り分けについては、PyCon JP当日のトーク（または別の記事で）お伝えします。