Help us understand the problem. What is going on with this article?

conda パッケージを Juliaから追加しよう

付記 2018/3/2

ENV["CONDA_JL_VERSION"]=3 してね。

→ [Julia] miniconda 3 を導入させるように指定した (= PyPlot が正しく動いた)
https://qiita.com/tenfu2tea/items/917dceb14687ffb1988c

元記事

Julia advent calendar 2016 5日目の記事です。

 今年の個人トピックに、mayavi というライブラリが anaconda パッケージで提供されるようになったことがあります。Python でしばらく楽しんでいましたが、Julia からも使いたくなりました。けれど、conda 環境を Julia から使う方法が分かりません。
 conda 環境を Julia から操作する仕組みは、PyCall.jlConda.jl の二つのパッケージが提供しています。これらの機能をユーザ目線で整理してまとめてみました。

前提

  • MacOS X 10.12.1 Sierra で実行した結果を以下に引用しました。(私のユーザ名は ___ で隠してあります)
  • カタカナの「パッケージ」は Julia パッケージを、ひらがなの「ぱっけーじ」は anaconda パッケージをそれぞれ指します。
  • カタカナの「モジュール」は Julia モジュールを、ひらがなの「もじゅーる」は Python モジュールをそれぞれ指します。(前者は記事中に出現しませんけれども)

PyCall 概説

 PyCall パッケージは、Julia から Python を呼び出すためのパッケージです。呼び出すだけでなく conda ぱっけーじを追加できます。
 PyCall パッケージは、自分でインストールしてなくても、Python を呼び出すパッケージをインストールする際に同時にインストールされることがあります。
 例えば、2次元グラフ描画のパッケージ PyPlot をインストールした場合のメッセージを一部抜粋してみましょう。PyCallConda パッケージもインストール (あわせてビルド)されています。

julia> Pkg.add("PyPlot")
INFO: Initializing package repository /Users/___/.julia/v0.5
INFO: Cloning METADATA from https://github.com/JuliaLang/METADATA.jl
...
INFO: Cloning cache of Conda from https://github.com/JuliaPy/Conda.jl.git
INFO: Cloning cache of PyCall from https://github.com/JuliaPy/PyCall.jl.git
INFO: Cloning cache of PyPlot from https://github.com/JuliaPy/PyPlot.jl.git
INFO: Installing Conda v0.4.0
INFO: Installing PyCall v1.7.2
INFO: Installing PyPlot v2.2.4
...
INFO: Building Conda
INFO: Building PyCall

PyCall が呼ぶ Python の場所

 PyCall を使うには using PyCall します。
 PyCall で呼び出される python インタプリタのバージョン、絶対パス、ライブラリパスは PyCall.pyversion, PyCall.pyprogramname,PyCall.libpython で、それぞれ得ることができます。

julia> Pkg.add("PyCall")  # 一度インストールすれば OK
...
INFO: PyCall is using python (Python 2.7.12) at /Users/___/.julia/v0.5/Conda/deps/usr/bin/python, libpython = /Users/___/.julia/v0.5/Conda/deps/usr/lib/libpython2.7  # PyCallを buildすると Pythonの実行パスとライブラリパスが表示されます

julia> using PyCall

julia> PyCall.pyversion
v"2.7.12"

julia> PyCall.pyprogramname
"/Users/___/.julia/v0.5/Conda/deps/usr/bin/python"

julia> PyCall.libpython
"/Users/___/.julia/v0.5/Conda/deps/usr/lib/libpython2.7"

 さて、上の Python は Julia 自身が追加したものです。
 PyCall パッケージをビルド Pkg.build("PyCall") する際に Python の実行ファイルが見つからないと、miniconda がインストールされます。 例えば、上で例に挙げた PyPlot は、matplotlib もじゅーるを使います。anaconda を自分で入れなくても matplotlib が使えるのは、この仕組みからですね。
 で。この miniconda-python の在処は、上の PyCall.pyprogramname が示すディレクトリ、つまり、ホームディレクトリ直下 .julia ディレクトリの下の Conda ディレクトリです。

@pyimport : Python もじゅーるをインポートする

 Python もじゅーるをインポートする (= Julia で使えるようにする)には、PyCall パッケージの @pyimport マクロを使います。
 例えば、matplotlib もじゅーるを、PyPlot を用いずに直に使ってみると、以下のような感じです。

julia> using PyCall

julia> @pyimport matplotlib.pyplot as plt

julia> plt.plot( [1,2,3] )

julia> plt.show()

 Python と見分けがつきませんが、これは @pyimport マクロが Python 型とJulia 型を相互に変換しているからです。
 Python に渡す引数の型や戻り値の型を細かく指定したい場合には PyCall.pycall 命令で pythonの関数を呼び出します。 この辺は、別の解説に譲ります。
 @pyimport マクロで、python もじゅーるが見つからないと例外が発生します。
 もう一つ、pyimport という命令があります。こちらは、Python もじゅーるをインポートしますが、 Python 型とJulia 型を変換する機能はありません。

pyimport_conda : conda ぱっけーじの追加

 PyCallパッケージの pyimport_conda() 命令を用いると、上の miniconda 環境に、Python もじゅーる(ぱっけーじ)を追加できます。
 呼び出し形式は
 pyimport_conda(modulename, pkg, [channel])
です。
 この命令では、最初に、Pythonの ぱっけーじ modulename を探索し、見つからないと pkg ぱっけーじを追加します。その後、上の pyimport(modulename, pkg, [channel]) を実行し、その戻り値を返します。
 例えば mayavi というもじゅーる (ぱっけーじ名も同じ)を追加するには、以下のようにします。

julia> @pyimport mayavi
ERROR: PyError (:PyImport_ImportModule) <type 'exceptions.ImportError'>
ImportError('No module named mayavi',)

julia> pyimport_conda( "mayavi", "mayavi")

 pyimport_conda は、次に説明する Conda.add() 命令を内部で呼び出しています。

Conda パッケージを用いた conda環境の操作

 Conda パッケージを用いて、miniconda 環境を操作できます。シェル (コマンドライン、ターミナル)から使う conda コマンドと同様の操作ができます。

  • Conda.list([env]) : インストールされている conda ぱっけーじ のリストを出力します。
  • Conda.add(pkg, [env]) : conda ぱっけーじ pkg を追加します。
  • Conda.rm(pkg, [env]) : conda ぱっけーじ pkg を削除します。
  • Conda.update([env]) : インストールされている conda ぱっけーじ を最新に更新します。

実行例を見てみます。

julia> Pkg.add("Conda")  # PyCallパッケージをインストールしたら、たいていインストール済炭です。

julia> using Conda

julia> Conda.PYTHONDIR
"/Users/__/.julia/v0.5/Conda/deps/usr/bin"

julia> Conda.list()
# packages in environment at /Users/___/.julia/v0.5/Conda/deps/usr:
#
apptools                  4.2.1                    py27_0
conda                     4.2.13                   py27_0
conda-env                 2.6.0                         0
configobj                 5.0.6                    py27_0
... # 省略

julia> Conda.add("mayavi")
Fetching package metadata .............
Solving package specifications: ..........

Package plan for installation in environment /Users/___/.julia/v0.5/Conda/deps/usr:

The following NEW packages will be INSTALLED:

    mayavi: 4.4.0-np19py27_0

Linking packages ...
[      COMPLETE      ]|###################################################| 100%
... # 省略

julia> Conda.rm("mayavi")
Fetching package metadata .............
Solving package specifications: ..........

Package plan for package removal in environment /Users/___/.julia/v0.5/Conda/deps/usr:

The following packages will be REMOVED:

    mayavi: 4.4.0-np19py27_0

Unlinking packages ...
[      COMPLETE      ]|###################################################| 100%
... # 省略

julia> Conda.update()
Fetching package metadata .............
Solving package specifications: ..........

Package plan for installation in environment /Users/___/.julia/v0.5/Conda/deps/usr:

The following packages will be downloaded:
package                    |            build
---------------------------|-----------------
openssl-1.0.2j             |                0         3.0 MB
... # 省略

 以上説明した Conda.list(), Conda.add(), Conda.rm(), Conda.update() を含めて、Conda の命令は全て env という省略可能パラメータをとります。env は 操作対象の minionda 環境を指定するもので、既定値は Conda.PYTHONDIR (miniconda環境の親ディレクトリのパス)です。

 標準ではない anacondaぱっけーじをインストールする際には、チャネル channel を指定できます。
- Conda.channels([env]): conda環境 env に含まれるチャネルのリストを出力します。
- Conda.add_channel(channel, [env]) : conda環境 env に、チャネルchannel を追加します。
- Conda.rm_channel(channel, [env]): conda環境 env から、チャネルchannel を削除します。

 既定のチャネルは "defaults" です。

julia> Conda.channels()
1-element Array{String,1}:
 "defaults"

Python - Conda 環境の変更

 PyCall の呼び出し先をを、自分でインストールした anaconda 環境に変更できます。1. 呼び出す Python パスの修正と、2. conda 環境の参照先の修正の、二つの手順を踏みます。

1. 呼び出す Python パスの修正

 ENV["PYTHON"] に、Python 実行ファイルのフルパスを指定します。
 次いで、仮想環境 (virtualenv)を用いて anaconda環境を構築した場合は、rm(Pkg.dir("PyCall","deps","PYTHON")) を実行します (ここ重要)。
 仕上げに Pkg.build("PyCall") で、PyCall をビルドします。

julia> using PyCall

julia> ENV["PYTHON"]="/anaconda/bin/python"
"/anaconda/bin/python"

julia> rm(Pkg.dir("PyCall","deps","PYTHON"))

julia> Pkg.build("PyCall")
INFO: Building Conda
INFO: Building PyCall
INFO: PyCall is using /anaconda/bin/python (Python 2.7.12) at /anaconda/bin/python, libpython = //anaconda/lib/libpython2.7

2. conda環境の参照先を変更する

 上では、PyCall で呼ぶ Python の実行パスが変更されただけです。
 conda環境の参照先を変更するには、シェル(ターミナル、コマンドライン)で作業します。
 最初に、Julia から呼び出されるための conda 環境を、新規に作成しておきます。その conda 環境のパスを環境変数 CONDA_JL_HOME に設定して julia -e 'Pkg.build("Conda")’ を実行します。

$ conda create -n conda_jl python
$ export CONDA_JL_HOME="/Users/___/.pyenv/versions/anaconda-2.4.0/envs/conda_jl"
$ julia -e 'Pkg.build("Conda")'
INFO: Building Conda

 以後は、Conda を用いて、この conda環境を操作できます。しかし、混乱しそうなので、私は、シェルからぱっけーじを追加・削除することにしています。

$ conda install mayavi -n conda_jl
Using Anaconda Cloud api site https://api.anaconda.org
Fetching package metadata .............
Solving package specifications: ..........

Package plan for installation in environment /Users/___/.pyenv/versions/anaconda-2.4.0/envs/conda_jl:
... 以下略。

3. Juliaがインストールした Python に戻す

Juliaがインストールした conda環境に再び戻してみます。 2. → 1. の順に戻すのが、確実のようです。

(1) condaの参照先を戻して

$ export CONDA_JL_HOME="/Users/___/.julia/v0.5/Conda/deps/usr"
$ julia -e 'Pkg.build("Conda")'
INFO: Building Conda

(2) python 参照先を戻します。

 ENV["PYTHON"] に空文字列を指定して Pkg.build("PyCall") します。

julia> ENV["PYTHON"]=""

julia> Pkg.build("PyCall")
INFO: Building Conda
INFO: Building PyCall
INFO: No system-wide Python was found; got the following error:
could not spawn `'' -c "import distutils.sysconfig; print(distutils.sysconfig.get_config_var('VERSION'))"`: no such file or directory (ENOENT)
using the Python distribution in the Conda package
... 省略

julia> Conda.PYTHONDIR
"/Users/___/.julia/v0.5/Conda/bin"

 以上の手順でたいてい conda環境の参照先は元に戻るのですが、戻らない場面も経験しました。最後の手段として "~/.julia/v0.5/Conda" 以下のファイルを削除してから ENV["PYTHON"]="" ; Pkg.build("Conda") で、miniconda環境をビルドします (強引?)。

予告

 以上で、解説は終わりです。この解説が、所望の conda ぱっけーじを Juliaから使うための参考になれば、うれしいです。
 明日の Julia Advent Calendar も、私の担当です。 本題である mayavi ぱっけーじを Julia から使ってみた例を紹介します。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away