JavaでPythonを呼び出す?


回答:


100

Jython:Python for the Java Platform- http://www.jython.org/index.html

Jythonを使用すると、JavaコードからPython関数を簡単に呼び出すことができます。これは、Pythonコード自体がjythonで実行されている限り、つまりサポートされていない一部のC拡張機能を使用しない限りです。

それがあなたにとってうまくいくなら、それは確かにあなたが得ることができる最も簡単な解決策です。それ以外の場合は使用できますorg.python.util.PythonInterpreter、新しいJava6インタープリターサポートから。

私の頭の上からの簡単な例-しかしうまくいくはずです:(簡潔にするためにエラーチェックは行われていません)

PythonInterpreter interpreter = new PythonInterpreter();
interpreter.exec("import sys\nsys.path.append('pathToModules if they are not there by default')\nimport yourModule");
// execute a function that takes a string and returns a string
PyObject someFunc = interpreter.get("funcName");
PyObject result = someFunc.__call__(new PyString("Test!"));
String realResult = (String) result.__tojava__(String.class);

JYthonをインストールしたか、インストールしたと思いますが、私はあなたが概説したコードを実行しようとし続けていますが、それは間違いとしてハイライトされています。Jythonのインストールは、pythonまたはjavaフォルダー内の特定のフォルダーに移動する必要がありますか?
Shahab

2
エラーはありません。JythonをNetbeansに統合するのに苦労しています
Shahab

エラーがない場合は機能するため、明らかにそうではありません;)「エラー」は実行時エラーを意味するのではなく、コンパイルエラーである可能性もあります。
Voo

私の悪いことに、それは言葉の不適切な使用でした。プロジェクトとnetbeansにjython.jarを追加しようとしていました。私はそれを理解しました
シャハブ

1
Python 2のサポート終了は2020年1月1日で、JythonはPython 2.7のみをサポートしています。つまり、基本的に死んでいるJythonはありません。最良の(最も簡単な)オプションはJep libです
garyee

62

遅かったのですが、これに対する私の答えを入力しようと思いました。JavaとPythonの間のリンクをどの程度強くしたいかについて、最初に考慮すべきいくつかの重要な点があると思います。

まず、 関数を呼び出すだけですか、それとも実際にPythonコードでJavaオブジェクトのデータを変更しますか?これは非常に重要です。引数の有無にかかわらず、いくつかのpythonコードを呼び出したいだけなら、それはそれほど難しくありません。引数がプリミティブである場合は、さらに簡単になります。ただし、PythonでJavaクラスにメンバー関数を実装させて、Javaオブジェクトのデータを変更する場合は、これはそれほど簡単ではなく、簡単でもありません。

第二に、私たちはcpythonを話しているのですか、それともjythonがしますか?私はcpythonがその場所にあると言います!私はこれがpythonがとてもクールな理由だと主張します!ただし、このように高度な抽象化を行うと、必要に応じてc、c ++にアクセスできます。あなたがJavaでそれを持つことができるかどうか想像してみてください。この質問は、とにかく簡単なので、jythonが大丈夫かどうかを尋ねる価値はありません。

だから私は以下の方法で遊んで、それらを簡単なものから難しいものまでリストしました:

JavaからJython

利点:簡単です。Javaオブジェクトへの実際の参照がある

短所: CPythonがなく、非常に遅い!

JavaのJythonはとても簡単です。これで本当に十分なら、素晴らしいです。しかし、それは非常に遅く、cpythonはありません!私はそうは思わないcpythonなしで生活する価値がある人生です!あなたはあなたのJavaオブジェクトのためにあなたのメンバー関数を実装するPythonコードを簡単に持つことができます。

Pyroを介したJavaからJython、CPythonへ

Pyroは、Pythonのリモートオブジェクトモジュールです。cpythonインタープリターにいくつかのオブジェクトがあり、シリアライゼーションを介して転送されるオブジェクトを送信したり、このメソッドを介してオブジェクトを返すこともできます。jythonからシリアル化されたpythonオブジェクトを送信し、そのメンバーのデータを変更するいくつかの関数を呼び出した場合、Javaでそれらの変更が表示されないことに注意してください。あなたはpyroから欲しいデータを送り返すことを覚えておく必要があるだけです。これはcpythonにアクセスする最も簡単な方法だと思います!jni、jna、swig、...は必要ありません。c、またはc ++を知っている必要はありません。ねえ?

利点:次の方法ほど難しくないcpythonへのアクセス

欠点: Pythonから直接Javaオブジェクトのメンバーデータを変更することはできません。多少間接的です(jythonは中間者です)。

JavaからC / C ++へ、JNI / JNA / SWIGからPythonへ、埋め込みインタープリターを介して(おそらくBOOSTライブラリを使用して?)

OMGこの方法は、気の弱い人には向いていません。まともな方法でこれを実現するのに非常に時間がかかったと私は言うことができます。これを行う主な理由は、Javaオブジェクトを完全に制御するcpythonコードを実行できるようにするためです。python(馬のようなもの)でjava(チンパンジーのようなもの)を試してみる前に、考慮すべき主要な重要事項があります。まず、インタープリターをクラッシュさせると、プログラムは完全に消灯します。そして、同時実行の問題から始めないでください!さらに、ボイラーの割り当ての割り当てがあります。このボイラーを最小限に抑えるための最良の構成を見つけたと思いますが、それでも割り当てです。だから、これをどうやってやるか:C ++があなたの仲介者だと考えてください、あなたのオブジェクトは実際にはc ++オブジェクトです!あなたが今それを知っているのは良いことです。あなたのプログラムをJavaではなくcppのように書くだけで、両方の世界からアクセスしたいデータ。次に、swigと呼ばれるラッパージェネレーターを使用できます(http://www.swig.org/Doc1.3/Java.html)これをJavaにアクセスできるようにし、JavaでSystem.load(dll name here)を呼び出すDLLをコンパイルします。最初にこれを機能させてから、難しい部分に進んでください!Pythonにアクセスするには、インタープリターを組み込む必要があります。最初に、いくつかのhelloインタープリタープログラムまたはこのチュートリアルC / CへのPythonの埋め込みを行うことをお勧めします。それがうまくいったら、馬と猿を踊らせる時です![boost] [3]を介してPythonにc ++オブジェクトを送信できます。私はあなたに魚を与えなかったのを知っています、ただ魚を見つける場所をあなたに話しました。コンパイル時にこれについて注意すべきいくつかのポインタ。

boostをコンパイルするときは、共有ライブラリをコンパイルする必要があります。そして、jdkから必要なもの、つまりjawt.lib、jvm.libを含めてリンクする必要があります(アプリケーションを起動するときに、パスにクライアントjvm.dllも必要です)python27.libまたは何でも、boost_python-vc100-mt-1_55.lib。次に、Python / include、jdk / include、boostを含め、共有ライブラリ(dll)のみを使用します。そうしないと、boostに問題があります。ええ、私は完全に知っています。これが酸っぱいことができる方法はたくさんあります。したがって、ブロックごとに各処理を実行するようにしてください。その後、それらを一緒に置きます。


2
ここでは、Pythonスクリプトを1回記述し、実行時に使用する統合方法(Jython、JepおよびPy4jを介したCPython)を決定できるライブラリ:github.com/subes/invesdwin-context-python各メソッドには独自の利点/欠点があるため
2017年

@subesそのプロジェクトは素晴らしく見えます。これは少し前に書いたものです。私はそれを支持する答えを書くことをお勧めします。グーグル検索以外の多くの有用な情報を提供するとは思わないので、私はトップの回答は嫌いです。
Snickers3192 2017年

私は別の回答を作成しました
投稿

3
この答えは「これは受け入れられる答えでなければならない」という匂いですか、それとも私だけですか?;-)
マウリシオグラシアグティエレス

18

Javaの内部にPythonコードを置くのは賢明ではありません。Pythonコードをフラスコまたはその他のWebフレームワークでラップして、マイクロサービスとして作成します。Javaプログラムがこのマイクロサービスを(たとえばREST経由で)呼び出せるようにします。

私を信じて、これは非常に簡単であり、あなたにたくさんの問題を救います。また、コードは疎結合されているため、スケーラブルです。

2020年3月24日に更新:@stxのコメントによると、上記のアプローチはクライアントとサーバー間の大量のデータ転送には適していません。ここに私が推奨する別のアプローチがあります:PythonとJavaをRustで接続します(C / C ++もOK)。 https://medium.com/@shmulikamar/https-medium-com-shmulikamar-connecting-python-and-java-with-rust-11c256a1dfb0


+1ですが、両端でのメッセージの作成と解析の追加のパフォーマンスと通信オーバーヘッドはどうですか?
stx

はい、これは最小限の入出力が必要なAPIインターフェースを定義する必要があります。ネットワーク上のクライアント/サーバー間で大量のデータ転送を行うのは賢明ではありません。そのようなインターフェースを定義できない場合、この設計アプローチは適していません。
Peiming Hu

10

回答のいくつかには、JNIまたはJNAを使用してcpythonにアクセスできると記載されていますが、Javaからcpythonにアクセスするためのオープンソースライブラリがすでにあるため、ゼロから始めることはお勧めしません。例えば:


8

ここでは、Pythonスクリプトを1回記述し、実行時に使用する統合方法(Jython、JepおよびPy4jを介したCPython / PyPy)を決定できるライブラリを示します。

https://github.com/subes/invesdwin-context-python

リンクで説明されているように、各メソッドには独自の利点/欠点があります。


このプロジェクトにはリリースがありません。
クリスチャンシュリクサーレ

@ChristianSchlichtherle invesdwin-context-pythonバージョン1.0.0は使用できません。この小さな宝石のおかげ:github.com/loewenfels/dep-graph-releaser
subes

6

それはあなたがPython関数によって何を意味するかに依存しますか?それらがcpythonで書かれている場合は直接呼び出すことはできませんが、JNIを使用する必要がありますが、jythonが最終的にJavaバイトコードを生成するため、Jythonで書かれている場合はJavaから簡単に呼び出すことができます。

今私がcpythonまたはjythonで書かれていると言っても、pythonはpythonであり、cpythonまたはjavaに依存する特定のライブラリを使用しない限り、ほとんどのコードは両方の実装で実行されます。

JavaでPythonインタープリターを使用する方法については、こちらをご覧ください


5

要件によっては、XML-RPCなどのオプションが役立つ場合があります。これは、プロトコルをサポートする任意の言語で仮想的に関数をリモートで呼び出すために使用できます。


5

GraalVMは良い選択です。マイクロサービス設計のためにJava + JavascriptとGraalVMを組み合わせました(Javascriptリフレクションを使用したJava)。彼らは最近pythonのサポートを追加しました。特に、コミュニティが何年にもわたって大きくなっていることを試してみます。


4

Java Native Interfaceを使用してJavaから任意の言語を呼び出すことができます


6
それ自体がcから呼び出すことができる任意の言語。まあまあのpythonはできますが、Jythonは実際にはもっと単純なソリューションです(またはj6 +でPyInterpreterを使用します)。CからPython関数を呼び出すコードを書くのはそれほど簡単ではありません。
Voo

2

Jythonにはいくつかの制限があります。

いくつかの違いがあります。まず、JythonプログラムはCで記述されたCPython拡張モジュールを使用できません。これらのモジュールには通常、拡張子が.so、.pyd、または.dllのファイルがあります。このようなモジュールを使用する場合は、純粋なPythonまたはJavaで記述された同等のモジュールを探す必要があります。そのような拡張機能をサポートすることは技術的に実現可能ですが-IronPythonはそうです-Jythonではそうする予定はありません。

JythonでPythonスクリプトをJARファイルとして配布していますか?

RuntimeまたはProcessBuilderを使用してJavaからPythonスクリプト(またはbashまたはPerlスクリプト)を呼び出し、Javaに出力を返すだけです。

Javaでのbashシェルスクリプトの実行

Javaでコマンドラインを実行する

java runtime.getruntime()コマンドラインプログラムの実行から出力を取得する


0

これにより、現在のオプションの概要がかなりわかります。それらのいくつかは他の回答で名前が付けられています。Jythonは、Python 3.xを実装することを決定し、他の多くのプロジェクトがPython側から来て、Javaにアクセスするまで使用できません。しかし、まだ名前が付けられていないものに名前を付けるには、いくつかのオプションがあります:gRPC

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.