问题:在Java中调用Python?
我想知道是否可以使用jython从Java代码调用python函数,还是仅用于从python调用Java代码?
回答 0
Jython:适用于Java平台的Python- 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);
回答 1
嘿,我想我会输入我的答案,尽管已经很晚了。我想首先要考虑一些重要的事情,即您希望在java和python之间建立多强的连接。
首先 ,您是否只想调用函数,或者您是否真的希望python代码更改Java对象中的数据?这个非常重要。如果您只想调用带或不带参数的python代码,那并不是很难。如果您的参数是基元,那么它将变得更加容易。但是,如果您想让Java类在python中实现成员函数,这些成员函数会更改java对象的数据,那么这并不是那么容易或直接的。
其次,我们在谈论cpython还是jython做?我会说cpython是它的所在!我主张这就是为什么python如此强大的原因!但是,在需要时具有如此高的抽象度却可以访问c,c ++。想象一下您是否可以在Java中使用它。这个问题甚至都不值得问jython是否还可以,因为这样很容易。
因此,我使用以下方法,并从容易到困难列出了它们:
Java到Jython
优点:轻而易举。实际引用Java对象
缺点:没有CPython,非常慢!
来自Java的Jython非常简单,如果确实够了,那就太好了。但是它非常慢并且没有cpython!没有cpython值得生活,我不这么认为!您可以轻松地让python代码为java对象实现成员函数。
通过Pyro从Java到Jython到CPython
Pyro是python的远程对象模块。您在cpython解释器上有一些对象,您可以向其发送通过序列化传输的对象,也可以通过此方法返回对象。请注意,如果您从jython发送一个序列化的python对象,然后调用某些函数来更改其成员中的数据,那么您将在java中看不到这些更改。您只需要记住从pyro发送回想要的数据。我相信这是进入cpython的最简单方法!您不需要任何jni或jna或swig或…。您不需要了解任何c或c ++。酷吧?
优点:访问cpython,不像以下方法那样困难
缺点:无法直接从python更改java对象的成员数据。有点间接,(jython是中间人)。
通过JNI / JNA / SWIG将Java转换为C / C ++,通过嵌入式解释器转换为Python(也许使用BOOST库?)
OMG这种方法不适合胆小的人。我可以告诉您,用一种体面的方法来实现这一目标已经花了我很长时间。您要执行此操作的主要原因是,您可以运行cpython代码,以完全控制您的java对象。在决定尝试使用python(就像一匹马)为java(像黑猩猩)做面包之前,需要考虑一些主要的主要事情。首先,如果您崩溃的解释器为您的程序点亮了!而且不要让我开始讨论并发问题!另外,还有锅炉分配器,我相信我已经找到了使该锅炉最小化的最佳配置,但仍然是分配器!那么该怎么做:考虑一下C ++是您的中间人,您的对象实际上就是c ++对象!很好,您现在就知道。只需编写您的对象,就好像您的程序在cpp中而不是java中一样,您想从两个世界访问的数据。然后,您可以使用名为swig(http://www.swig.org/Doc1.3/Java.html),以使Java可以访问此文件并编译一个dll,您可以在java中调用System.load(此处为dll名称)。首先使此工作正常,然后继续进行困难的工作!要使用python,您需要嵌入一个解释器。首先,我建议您编写一些hello解释程序或本教程 python嵌入C / C中。一旦完成这项工作,就该让马和Monkey跳舞了!您可以通过[boost] [3]将c ++对象发送给python。我知道我没有给你鱼,只是告诉你在哪里可以找到鱼。编译时需要注意的一些指针。
编译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
在Java中包含python代码并不明智。用flask或其他Web框架包装您的python代码,使其成为微服务。使您的Java程序能够调用此微服务(例如,通过REST)。
相信我,这很简单,可以为您节省很多问题。而且代码是松散耦合的,因此它们是可伸缩的。
于2020年3月24日更新:根据@stx的评论,上述方法不适用于客户端和服务器之间的海量数据传输。这是我推荐的另一种方法:使用Rust连接Python和Java(也可以使用C / C ++)。 https://medium.com/@shmulikamar/https-medium-com-shmulikamar-connecting-python-and-java-with-rust-11c256a1dfb0
回答 3
回答 4
这里是一个库,可让您一次编写python脚本并确定在运行时使用哪种集成方法(Jython,CPython / PyPy(通过Jep和Py4j)):
https://github.com/subes/invesdwin-context-python
由于每种方法都有其自身的优点/缺点,如链接中所述。
回答 5
这取决于您对python函数的含义是什么?如果它们是用cpython编写的,则不能直接调用它们,则必须使用JNI,但是如果它们是用Jython编写的可以轻松地从Java调用它们,因为jython最终会生成Java字节码。
现在,当我说用cpython或jython编写时,这没有多大意义,因为python是python,并且除非您使用依赖于cpython或java的特定库,否则大多数代码都可以在两种实现上运行。
请参阅此处如何在Java中使用Python解释器。
回答 6
根据您的要求,诸如XML-RPC之类的选项可能会很有用,它可以用于虚拟地以任何支持协议的语言远程调用函数。
回答 7
GraalVM是一个不错的选择。我已经完成了与GraalVM的Java + Javascript组合用于微服务设计(具有Javascript反射功能的Java)。他们最近增加了对python的支持,我想尝试一下,尤其是多年来这些社区的规模。
回答 8
您可以使用Java Native Interface从Java调用任何语言
回答 9
Jython有一些限制:
有许多差异。首先,Jython程序不能使用用C编写的CPython扩展模块。这些模块通常具有扩展名为.so,.pyd或.dll的文件。如果要使用这样的模块,则应寻找用纯Python或Java编写的等效模块。尽管在技术上支持此类扩展是可行的-IronPython这样做-在Jython中尚无计划这样做。
使用Jython将我的Python脚本作为JAR文件分发吗?
您只需使用Runtime或ProcessBuilder从Java调用python脚本(或bash或Perl脚本),然后将输出传递回Java:
回答 10
这样可以很好地概述当前的选项。其中一些在其他答案中被命名。在他们决定实现Python 3.x之前,Jython不可用,并且许多其他项目都来自python方面并希望访问java。但是,还有一些选项可以命名尚未命名的名称:gRPC