私の周りでも pyenv に対して良い印象をもって語らない風潮はあってその理由がよく分かりました。ここで @shibukawa が書いていることを私は正しいと思うし、pyenv というツールそのものを批判しているのではなく、目的や用途を理解せずに pyenv を勧めたり使ってしまったりしてしまう人への懸念があるというのは理解できました。
ちなみに私は普段 OS X と Linux (Ubuntu) を使っているのですが、Linux では pyenv を、OS X では MacPorts を使って複数の Python バージョンの管理をしています。件の記事の分類でいうと「ライブラリの開発者」のところだと思います。
pyenv の議論は件の記事を読んでもらうとして、そこでは Anaconda についても触れています。Anaconda を pyenv の議論に混ぜてしまうのは雑過ぎると私は感じました。本稿では Anaconda についての補足をします。
ちなみに私は普段 Anaconda を使っているわけではなく、ましてやデータサイエンティストでもないのでその業界の雰囲気や状況に関しては全く知りません。Anaconda を提供している Continuum Analytics 社のサイトのドキュメントを読んで分かる範囲で書いているのでそれ以上でもそれ以下でもないです。
Anaconda とはディストリビューションである
Anaconda の概要を読むと Anaconda Distribution という単語が目につくと思います。Anaconda は明示的にディストリビューションであると宣言しています。
このディストリビューションという概念が開発者であっても日本ではあまり一般的ではないことから pyenv と Anaconda をごちゃ混ぜにした議論になってしまうのではないかと思います。
ディストリビューションとは何か
ググって出てくるものの中には
ディストリビューションとは Linux ディストリビューション、、、
といった記述も見かけます。最も一般的であると思われるディストリビューションが Linux ディストリビューションであることは、狭義ではそうかもしれませんが、本稿では wikipedia の ディストリビューション に書いてある
コンパイル済みで設定済みのソフトウェアの集まり。また、配布者のことをディストリビューターと呼ぶ。
という広義の定義を使うとします。何らかの目的のために一連のソフトウェア群を提供したものを広義のディストリビューションと呼びましょう。
Linux ディストリビューションの価値とは何か
Anaconda のような、アプリケーションのディストリビューションの話に入る前に、多くの人にとって馴染みのある Linux ディストリビューションを例に説明してみます。
wikipedia の説明にもあるようにディストリビューションでは コンパイル済みで設定済みのソフトウェアを提供する ことに大きな価値があります。Gentoo Linux のようなコンパイル済みではなく自分でコンパイルしないといけない Linux ディストリビューションもありますが、こちらの方が少数派だと思うのでここでは許してください。
ソフトウェアのディストリビューションの配布形態は大きく分けて2つあります。
- コンパイル済みのソフトウェアを配布するバイナリーディストリビューション
- ソースファイルをそのまま配布するソースディストリビューション
多くのディストリビューションはこの2つの両方を提供していて、バイナリー/ソースディストリビューションを容易に行うための仕組みを パッケージ管理システム といい、そのツールをパッケージマネージャーと呼びます。有名な Linux ディストリビューションをみてもらえば分かると思いますが、それぞれの Linux ディストリビューターが独自開発して提供するものがパッケージ管理システムであり、パッケージマネージャーです。
ここでオリジナルのソフトウェアをパッケージ管理システムで配布するために付加情報 (メタデータ) も含めたものを パッケージ と呼びます。なぜ付加情報を付ける必要があるかというと、次のような機能をパッケージ管理システムで提供するために必要だからです。
- バージョン管理
- 依存関係の解決
- パッチの適用
- 署名の適用
- 履歴 (changelog) の確認
多くの開発者はバイナリーディストリビューションを使ってパッケージを管理し開発環境を整備します。バイナリーディストリビューションを使う大きなメリットはコンパイル時間の短縮です。マシンのスペックにも依りますが、ただライブラリやツールを使いたいだけなのに何時間もコンパイルが終わるまで待つということができないせっかちな開発者の方が多いと思います。私もそのうちの1人です。
バイナリーディストリビューションを使えば、コンパイル時間をなくせることが分かりました。そのソフトウェアを提供する本家のコミュニティがそれを提供していて、それを使えば良いというのは独立したソフトウェアであればそうかもしれません。
ようやく本題の Linux ディストリビューションの価値に入っていきますが、ある程度の規模以上のアプリケーションやライブラリなどでは、内部的にその他たくさんのライブラリを使っています。全てのライブラリを揃えないと完全な機能は使えませんし、場合によっては一部のライブラリがないだけで起動すらしないかもしれません。パッケージマネージャーの機能の1つにも書きましたが、 依存関係の解決 によって Linux ディストリビューションが提供しているパッケージは、それぞれのパッケージが整合性をもってちゃんと使える (動く) ことを保証しています。
例えば、Ubuntu 16.04 LTS を初期インストールした状態だと、2000 近くのパッケージがインストールされています。私にとって必要ないパッケージもたくさんインストールされていると思いますが、1000 を超えるパッケージを取捨選択して、それぞれの依存関係やバージョンの互換性を調べるのは大変な労力となります。
最も分かりやすい Linux ディストリビューションの価値とは、ユーザーが必要なソフトウェアのバージョンや依存関係を解決する労力を削減して、それらが既に解決されたディストリビューションであることです。
さらに補足すると、Linux ディストリビューターが提供する価値には以下のようなものもあります。
- 本家が提供しないバージョンへのセキュリティイシューに対してもパッチを適用して配布してくれる
- Linux ディストリビューションのパッケージ管理システムを使うことで ISV (サードパーティー) が提供するソフトウェアをインストール/アップグレードのコストを削減できる
- ISV が提供する商用サポートの環境を限定することによりサポートコストを削減できる
他にもたくさんあると思いますが、私がパッと思いつくものをあげています。
システムのためのパッケージ管理とアプリケーションのためのパッケージ管理
Linux ディストリビューションを例にディストリビューションにはどういった価値があるのかをざっくり把握できました。パッケージ管理は Linux ディストリビューターに任せておけば楽でいいですねという時代も過去にはありましたが、最近はそういうわけにもいかなくなってきました。例えば、Web 開発者がアプリケーションを開発/提供するのに使うライブラリが大幅に増えて多様化し、それぞれの依存関係やバージョン管理ももっと複雑になってしまいました。Linux ディストリビューターが管理できないレベルに膨れ上がってしまいました。
まずシステム領域とユーザー領域の違いを説明します。
- システム領域: システムが利用するアプリケーションやライブラリを置いてある場所
- ユーザー領域: ログインしたユーザーが自由に使える領域
例えば Ubuntu ではインストールされた Python インタープリターは /usr/bin の配下に、標準ライブラリや外部のライブラリは /usr/lib の配下にインストールされます。
$ which python
/usr/bin/python
$ ls /usr/lib/python3.5/
LICENSE.txt
__future__.py
...
$ ls /usr/lib/python3/dist-packages
...
システム領域にあるものをユーザーが使う分には自由に使って良いですが、勝手にそれを置き換えることには十分な注意が必要となります。それは先ほど説明した Linux ディストリビューターが労力をかけて整合性のあるライブラリの依存関係やバージョンに調整したものを壊してしまう可能性があるからです。こうなると、Linux ディストリビューターの提供する価値が大きく損なわれてしまいます。場合によってはシステムが正常に動作しなくなってしまうこともあるでしょう。
システム管理という側面から、システム領域にあるものを Linux ディストリビューターが提供していないものに変更してシステムそのものが正常に稼働しなくなってはアプリケーションの開発どころの話ではありません。しかし、自分が作りたいアプリケーションに必要なバージョンのパッケージを Linux ディストリビューターが提供してくれない場合にはどうしたら良いでしょうか。
そういったシステム管理者とアプリケーション開発者のお互いの要件を満たすためにシステム管理のためのパッケージ管理と、アプリケーションのためのパッケージ管理は分けて考えましょうということになりました。そのためにアプリケーションに必要なものはユーザー領域にインストールしてシステムには影響を及ぼさない方法が取られるようになってきました。pyenv や virtualenv の有用性の1つがそういった点です。
余談ですが、Linux は Python2/3 で1つのバージョンしか提供していないというのは、Linux ディストリビューターの視点からみると、システムに必要な Python のバージョンを1つに固定した方が内部で Python を使っているシステム管理ツールなどの品質向上や、パッケージャー (パッケージングをする人) がパッケージングのための作業工数を減らせるので複数の Python バージョンを提供していないのだと思います。
一方で OS X の MacPorts/Homebrew は複数の Python バージョンを提供しているのはそれを Apple が行っているわけではなく、有志のメンテナーがその作業負担をしてくれているというだけではないかと思います。
アプリケーションのためのパッケージ管理
Linux ディストリビューションから Python の話に戻ります。Python でアプリケーションを開発するために Python コミュニティとして PyPA というワーキンググループがパッケージ管理の標準化を進めています。詳細は @aodag の PyCon JP 2016 の発表内容に譲りますが、パッケージマネージャーとしては pip というツールが提供されています。
以前は Python のパッケージ管理は Python で書かれたスクリプトファイルを配布するというソースディストリビューションが主流でしたが、最近では wheel というバイナリーディストリビューションを配布する仕組みも普及してきつつあります。
余談ですが、バイナリーディストリビューションが求められる背景は CI (継続的インテグレーション) の一般化による影響が大きいのではないかと思います。以前は、社内の CI サーバーであらかじめいくつか環境を構築していれば良かったものが、外部の CI サービスが一般化されて環境構築を早くするためのバイナリーディストリビューションが求められるのは必然と言えるでしょう。
アプリケーションのディストリビューションとは何か
Linux ディストリビューションではシステム領域とユーザー領域という考え方があり、システム領域にあるコマンドやライブラリなどを変更するのは好ましくないとされています (しても良いけど、自己責任) 。
Anaconda はアプリケーションのディストリビューションであるとサイトに書いてありました。アプリケーションのディストリビューションはどう在るべきなのかというのが大きな焦点となります。但し、ディストリビューターが提供する価値の本質とは何かという観点では Linux ディストリビューターのそれと同じではないかと私は思います。
また Anaconda がその分野の先駆者でもなく昔からアプリケーションのディストリビューションというものもたくさんあります。例えば CPython を含むアプリケーションのディストリビューションとしては Anaconda 以外にもいくつか提供されているのが以下のサイトから分かります。
私の知る限り、Python 界隈でアプリケーションのディストリビューションがここまで普及したと言えるのは Anaconda が初めてではないでしょうか。それだけ Anaconda が提供している価値が、それを望む人たちのニーズにマッチしたのではないかと思います。
Anaconda が提供している価値とは何か
Anaconda はアプリケーションのディストリビューションであると同時に多くの機能を提供しています。
- バイナリーディストリビューションであること
- Python インタープリターをインストールしてくれること
- Anaconda 上で有効なパッケージ管理システム (conda) を内包すること
- Anaconda 上で有効な Environment Isolation Tool (環境分離ツール) であること
- Anaconda 上で有効な複数の Python バージョンの切り替え環境であること
特にタイトルに Anaconda は Environment Isolation Tool (環境分離ツール) ではない と付けましたが、Anaconda 上ではその機能が提供されています。これらの Anaconda 上で有効な機能が、Anaconda を pyenv や virtualenv と同じ土俵で議論させてしまうという分かりにくさにつながっているのだと思います。まず Anaconda を使っている人がその外の世界にある pyenv や virtualenv の議論をすることは適切だとは言えません。Anaconda という閉じた環境の中で仮想環境の話をするのは構いません。
Anaconda を使う以上、そこで発生した問題は基本的には全て Anaconda 上で解決すべきでしょう。そういった環境構築の煩雑さは初心者にとって分かりにくい、特に Anaconda の主なユーザーであるデータサイエンティストにとってそうなのかもしれません。
私の想像で書きますが、Anaconda を使う主なユーザーは @shibukawa の記事にある OS 毎の環境構築の違い、その背景となるパッケージ管理の違い、その代替となる作業手順などに興味はないでしょう。多くの Web 開発者が Linux ディストリビューションのパッケージ管理システムの詳細を知らずに、アプリケーションごとのパッケージ管理しかしないように。
データサイエンティストのうち、OS の仕組みや開発環境の構築方法を自分で調べて必要なツールやライブラリをビルドできるようにビルド環境を整備している人たちは少数派でしょう。もちろんそれぞれのツールやライブラリの本家が wheel でバイナリーディストリビューションを提供すればそれでいいかもしれませんが (numpy や pandas は提供されている) 、データサイエンスに必要な全てのツールやライブラリがそうなるのはまだ時間がかかると思います。
Anaconda がシステム領域のコマンドを隠すのは悪いことなのか
Anaconda はユーザー領域にインストールできるディストリビューションではありますが、OS X/Linux で Anaconda 環境を利用するには環境変数の PATH を設定して使います。これにより、Anaconda が持っているコマンドがシステム領域にあるコマンドより優先されて使われるようになってしまいます。
件の記事ではそれが良くないという指摘をしています。
Anacondaの/binをパスに設定するのですが、Anacondaがなかで持っているツール(openssl/curl/python)がOSの持っているツールを覆い隠してしまいます。あと、BASH前提になりすぎてて、zsh使ってると色々直さないと動きません。ちょっとこれはPythonを普段使っている人には影響がでかすぎる。もちろん、Windowsならバッティングするものはないので、問題ないと思います。
その振る舞いについて @shibukawa が登録した issue は以下になります。
(本稿執筆時点で) 回答がないので私が勝手に推測で書きますが、ディストリビューターという観点からみると、そのディストリビューション内で使うものはなるべくディストリビューションが責任をもつようにしたいというのは自然な考え方であるように私は思います。
そういう意味でディストリビューションの外側にあるシステム領域のコマンドを使うのが必ずしも正解であるとも限りません。先に述べたアプリケーションのパッケージ管理が必要になった背景は、システム領域で使うアプリケーションのバージョンと、ユーザー領域で使いたいそれとの乖離から発展してきたという経緯もあります。ユーザー領域にインストールするアプリケーションのディストリビューションがシステム領域のコマンドを、Anaconda を使うときだけ置き換えてしまうことにどのぐらいの影響があることなのか、私にとっては経験不足でよく分かりません。
但し、Linux ディストリビューションに代表されるようなシステムを含むディストリビューションと、Anaconda のようなアプリケーションのディストリビューションでお互いの管理する範囲をどう決めるべきなのかという課題を明確にすることは大事だと思います。 @shibukawa が指摘するように OS がもっている PATH 設定を代替する仕組みを使う、もしくはコマンド名を重複しないようにしてシステム領域のコマンドを隠さないようにするといった施策はその解決策の1つであるし、それでいいかもしれません。
Anaconda が提供したい価値とは何か
以下のものだとあります。
- Open Data Science
- Data Science Collaboration
- Self-Service Data Science
- Data Science Deployment
Open Data Science については別途解説があるので後に述べますが、その他の項目をざっと要約するとこんなことじゃないかと思います。
あるデータサイエンティストが作ったモデルや環境をチーム内で共有したり、再利用できるようにすることはデータサイエンスを活性化したり、データ解析によって大きなビジネスインパクトを与えることにもつながる、とあります。但し Data Science Deployment というのは Web 開発者が普段行っているようなデプロイではなく、Anaconda インストールしておけばどこでも同じものが使えるよといったレベルのものではないかと推測します。
Open Data Science とは何か
私は初めて聞く言葉です。わざわざページを作って説明していることから Continuum Analytics 社が提唱しているビジョンかもしれません。
Open Data Science is not a single technology, but a revolution within the data science community. Open Data Science is an inclusive movement that makes open source tools for data science - data, analytics and computation - easily work together as a connected ecosystem.
簡単に訳してみます。
Open Data Science とは単一のテクノロジーではありませんが、データサイエンスコミュニティの中で起こっている革命です。Open Data Science は、エコシステムと結びついた形でデータサイエンス (データ解析やその処理) 向けのオープンソースのツールを簡単に使えるようにするといった包括的な活動を指します。
Open Data Science の背景にある要素として以下のキーワードがあげられています。詳細はサイトを読んでください。
- 可用性
- イノベーション
- 相互運用性
- 透明性
さらにサイトにおもしろい説明があるので紹介します。
これまでのデータサイエンスは水泳のチームのように、個々人が目標を達成すればチームとしても成功であり、それぞれのチームメンバーの成果は独立していて非同期なものでした。
今日のデータサイエンスチームはサッカーチームのように、それぞれのメンバーが自分のレーンだけに制限されたものではなく、自由にフィールドを動いて自分たちのスキルを活かせるところでコントリビュートするのが推奨されています。
ここで Linux ディストリビューションが提供している価値について説明した節を思い出してください。そのことから Open Data Science が目指していることとの類似点を考えてみましょう。ディストリビューションであるがために、一定の環境の制約が出来てしまうのはそうですが、その環境を他人と共有するのが容易となります。
例えば、データサイエンティストのチーム全員に同じ Anaconda のバージョンをインストールしておき、あるメンバーが作ったモデルを別のメンバーへ渡して検証してもらうといったときの、環境構築に割く手間暇は大きく下がるでしょう。そしてその環境の維持もディストリビューターである Continuum Analytics 社がチームメンバーの代わりに行ってくれます。
いまデータサイエンスのコミュニティで起こっていることはこれまで個人が自由に環境を作って研究していたやり方が、その成果をみんなで共有するという方向へ移ってきているのではないでしょうか。そのためのプラットフォームとして Anaconda というディストリビューションがデータサイエンティストのニーズにうまく応えているから普及しているのでしょう。
まとめ
長くてすみません。言いたいことはこんな感じだと思います。たぶん。
- Anaconda はディストリビューションであり、Python インストーラーでも環境分離ツールでもない
- Anaconda と他のツールを混ぜるのは本来 Anaconda の意図した使い方ではない。但し、システムとの境目はちょっと曖昧ではある
- データサイエンスコミュニティ (データサイエンティスト) が OSS 的な世界中の人たちと協調して成果をみんなで共有するという方法論に目覚めた
リファレンス
@knzm に Conda: Myths and Misconceptions という Anaconda/Conda にまつまる誤解についてまとめられた記事を教えてもらいました。Anaconda はディストリビューションであるとここでも確認した上で Conda と pip のパッケージマネージャーとしての目的の違いなどにも言及しています。