ClojureとPythonの悪魔合体の奇跡を求めてlibpython-cljをハックする

以下の記事の続編.

Clojureで仮想通貨取引所のAPIを叩くライブラリを自作していたけれども, もしかしてccxtがつかえるのでは?と思い立ったのでの実験してみる. 採用するかどうかはまだ少しいじってみてから.

ccxtはPython/JavaScript/PHPの言語をサポートしている. ClojureScriptからJavaScriptを呼べば確実に呼べるんじゃね? という感じだが残念ながらわたしはJavaScritpが苦手でPytyonが得意なのだ. そしてClojureScriptではなくClojureを選んでいるのもわたしはJavaが大得意なのだ(爆). 不具合が起きたときに鼻が利く言語のほうがいい.

Python経由でccxtを叩いてつかっていくかもわからない. なぜならばもうすでにClojureで取引所を叩く方法はマスターして実装も多分ササッとできるから. どちらかというと, libpython-cljという謎のライブラリに対する好奇心がある. これをはつかうと果たしてClojureからPythonを呼び出すという変態的な行為ができるのだろうか, ということだ.

今回は業務上の理由でBitflyerはやめてFTXのtickを取得します.

libpython-cljでHelloWorld

https://github.com/clj-python/libpython-clj

まずは礼を尽くしてお辞儀をするように, 入門に際してHelloWorldをする.

;; 初期化
(require '[libpython-clj2.python :as py])
(py/initialize!)

;; pritty print moduleの読み込み
(require '[libpython-clj2.require :refer [require-python]])
(require-python '[pprint :as pp])

(pp/pprint "Hello,World.")

initialize!でPythtonを初期化. require-pythonでPythonのモジュールを何でも呼び込める.

よくネットの記事ではnumpyとかpandasも読み込んでいる.

libpython-cljでccxt.fetch_ticker

こんな感じで難なく成功.

(require '[libpython-clj2.require :refer [require-python]])

(py/initialize! :python-executable
                "~/miniconda3/envs/bakuchi/bin/python3.10"
                :library-path
                "~/miniconda3/envs/bakuchi/lib/libpython3.10.so")

(require-python '[ccxt])
(require '[libpython-clj2.python :as py :refer [py. py.. py.-]])

(def ex (ccxt/ftx))
(def tick (py. ex fetch_ticker "BTC/JPY"))

initialize!関数にpythonの実行バイナリを指定することでたとえばAnaconda環境も参照することはできる.

Clojureだと. Java Interopで(. object method)みたいなシンタックスになるが, Pythonだと(py. object method)みたいなシンタックスになる. Clojureを書いていればJava Interopは慣れ親しんだものなので, それに近いかたちでPythonを使えるのはよい.

戻り値は, Mapではなくてpyobjectという独特の型になっている. ->jvm というメソッドでMapに変換できる.

(def tick
  (when-let [resp (py. ex fetch_ticker "BTC/JPY")]
    (-> resp py/->jvm)))

https://gist.github.com/tsu-nera/3cdb908d1b9e6f9bcea68542777221e2

libpython-cljをつかってみた感想

わたすのボロビーシーの成果もしれないが, Pythonのinitialize!だったりモジュールロードに時間がかかった(Clojureに比べて).

ただClojureからPythonをつかってみました!というやってみた系ライブラリというよりは, 色んな人が(ドキュメントも)メンテに入っていてこれから人気にしたいという勢いも感じた(ClojureScriptのヒットの次に続け的な). もともとPythonをCでカリカリパフォーマンスチューニングをやっていたような人が開発しているのでClojureでも速度のチューニングに力入っている?

ref. Extending Clojure with Python - Chris Nuernberger - YouTube

ただClojureからPythonを呼べるようにしたというだけで, ClojureScriptのようなそこからの独自進化はない. これから変わっていくかもしれないしこれから変わるとするとproductionというよりはadhocな分析や実験的なコード用かもしれない.

そしてClojureからJavaのライブラリを呼べるといっても実際にClojureを書いているとできればJavaを呼びたくないというへんなインサイトを得たので, Pythonでしかできないこと以外は呼びたくないというのも当てはまりそう. しかし他の事例ではTensorflowでもPytorchでもHuggingFaceでもなんでも呼び出しているようなところをみると, DeepLearning系は強そう.

そして一旦REPL駆動開発の心地よさを知ったら他の言語をやりたくないなと思ってしまったら, PythonですらREPLに取り込むことは魅力かもしれない.