はじめに
py4jを使ってpythonからjavaのメソッドを呼び出す方法です。
日本語ドキュメントが古いものばかりで苦労したのでまとめてみました。
環境
OS X Yosemite 10.10.5
anaconda 3.5.0(python 3.5.2)
インストール
pip でpy4jをインストール後、Java側でpy4jを読み込めるようにjarをコピーします。
$ pip install py4j
$ sudo cp ~/.pyenv/versions/(仮想環境名)/share/py4j/py4j(バージョン).jar /Library/Java/Extensions/
実装
公式チュートリアルの通り、Javaで足し算を行う簡単なサンプルを作成してみます。
まずは以下のようなJavaプログラムを作成します。
import py4j.GatewayServer;
public class AdditionApplication {
public int addition(int first, int second) {
return first + second;
}
public static void main(String[] args) {
AdditionApplication app = new AdditionApplication();
// app を gateway.entry_point に設定
GatewayServer server = new GatewayServer(app);
server.start();
System.out.println("Gateway Server Started")
}
}
作成したら、以下のコマンドでサーバーを起動します。
$ javac AdditionApplication.java
$ java AdditionApplication
次に、AdditionApplication を呼び出すためのpythonプログラムを書いていきます。
from py4j.java_gateway import JavaGateway
# JVMへ接続
gateway = JavaGateway()
# java.util.Randomインスタンスを作成
random = gateway.jvm.java.util.Random()
# Random.nextIntを呼び出し
number1 = random.nextInt(10)
number2 = random.nextInt(10)
print(number1,number2) # (2, 7)
#AdditionApplicationのインスタンスを取得
addition_app = gateway.entry_point
# additionを呼び出し
sum_num=addition_app.addition(number1,number2)
print(sum_num) # 9
ひとまずはpythonから呼び出せています。
ですが、サーバーの起動・停止をわざわざターミナルから行うのは若干手間です。
どうせなら、最初から最後までpythonで実行できるようにします。
# クラスパスを指定して実行
args=(["java","-cp",'/path/to/class/','AdditionApplication'])
p=subprocess.Popen(args)
# サーバー起動前に処理が下へ行くのを防ぐ
time.sleep(3)
gateway = JavaGateway(start_callback_server=True)
random = gateway.jvm.java.util.Random()
n1 = random.nextInt(10)
n2 = random.nextInt(10)
print(number1,number2) # (2, 7)
addition_app = gateway.entry_point
print(addition_app.addition(n1, n2)) # 9
# プロセスをkill
gateway.shutdown()
最後まで一貫してpythonで実行できるようになりました。
Javerな人のプロジェクトを受け継いだ時や、使用したいJavaライブラリがある時、スピードの必要な処理を一部Javaで実装したい時等に使えるんじゃないでしょうか。
参考
https://www.py4j.org/
https://gist.github.com/bartdag/1070311