PythonからJavaのライブラリを呼び出して使う方法には以下のようなものがあります。
Jython
インタプリタ自体がJavaで実装されているので、Pythonスクリプトの中で
Javaのクラスや標準ライブラリがそのまま使えます。
一番手っ取り早いですが、CPythonとの互換性が問題になります。
(CPythonの標準ライブラリが一部対応していないなど)
Jythonでjarファイルを呼び出す方法についてはこちら
http://qiita.com/mojaie/items/9add34871a43c4181af7
JPype
CとJavaを連携するJNIを介して、PythonからJavaクラスを呼び出します。
CPythonからJavaをスムーズに呼び出せますが、インストール作業が非常に面倒です。
(Cコンパイラなど依存モジュールの相性によってはインストールすら出来ないことも)
Py4J
Javaの仮想マシン上でサーバを起動し、ソケット通信でCPythonとJavaを連携します。
上述の方法に比べると動作が遅いですが、JavaとPythonが完全に独立しているので、
比較的簡単に環境が構築でき、パッケージ化も容易です。
今回は、Py4Jを用いてjarファイルを呼び出す方法を紹介します。
インストール
pip install py4j
python、javaをインストールしてない場合はインストールしてください。
インストールフォルダ(shareフォルダ?)にpy4j0.7.jarというファイルが含まれているので、
適当な場所にコピーしてJavaのCLASSPATHを通しておきます。
Javaサーバプログラムの作成
まず、既存のjavaクラスを呼び出すためのサーバ用クラスを作ります。
下記は、JClassというクラスのgetStringというメソッドを呼び出すための
JClassEntryPointクラスの例です。
import py4j.GatewayServer;
public class JClassEntryPoint {
private JClass jclass = null;
public JClassEntryPoint() {
this.jclass = new JClass();
}
public String getString(String str) {
return jclass.getString();
}
public static void main(String[] args) {
GatewayServer gatewayServer = new GatewayServer(new JClassEntryPoint());
gatewayServer.start();
}
}
class JClass {
private String str = "hogehoge";
public String getString(String str) {
return this.str;
}
}
JClassEntryPoint.javaを実行可能なjarファイルにしておきます。
呼び出し側Pythonスクリプトの作成
まずsubprocessを使って上述のjarファイルを実行します。
サーバが起動し、JavaGatewayを介してJavaのクラスを読み込めるようになります。
また、atexit.register()を使うことで、Pythonスクリプト終了時に
自動的にサーバを終了させることができます。
time.sleep(2)はサーバが起動する前にJavaGatewayがサーバと通信しようとするのを
防ぐための苦肉の策です。もっといい方法があると思います。
import atexit
import subprocess
import time
from py4j.java_gateway import JavaGateway
class JClassClient(object):
def __init__(self):
self._gateway = None
self._process = None
cmd = ["java", "-jar", "/path/to/jarfile/JClassEntryPoint.jar", "JClassEntryPoint"]
self._process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stdin=subprocess.PIPE)
print "jvmprocess started: " + str(self._process.pid)
atexit.register(self._process.kill)
time.sleep(2)
self._gateway = JavaGateway()
def getString(self):
return self._gateway.entry_point.getString()
def main():
client = JClassClient()
print client.getString()
if __name__ == "__main__":
main()