在Java中调用Python?

127 人关注

我想知道是否可以用Jython从Java代码中调用Python函数,还是只适用于从Python调用Java代码?

1 个评论
请看一下类似的问题并阅读答案。 bytes.com/topic/python/answers/...
java
python
jython
Shahab
Shahab
发布于 2012-01-18
12 个回答
Voo
Voo
发布于 2021-07-10
已采纳
0 人赞同

Jython。Java平台上的Python - http://www.jython.org/index.html

你可以用Jython轻松地从Java代码中调用python函数。只要你的Python代码本身在jython下运行,即不使用一些不被支持的c扩展。

如果这对你有用,这当然是你能得到的最简单的解决方案。否则你可以使用新的Java6解释器支持中的 org.python.util.PythonInterpreter

一个简单的例子,来自我的头顶--但我希望应该是有效的:(为简洁起见,没有做错误检查。)

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);

从2021年起,Jython不支持Python 3.x。

我已经安装了JYthon,或者说我想我已经安装了,我一直试图运行你概述的代码,但它突出显示为一个错误。JYthon的安装是否需要进入一个特定的文件夹,无论是在python文件夹还是在java文件夹?
没有任何错误,我只是在将Jython集成到Netbeans中时遇到了困难。
Voo
如果没有错误,它就会工作,所以这显然不是事实;)"错误 "并不是指运行时错误,也可能是编译错误。
Python 2的生命末期是1.1.2020,而Jython只支持Python 2.7,所以没有Jython基本上就死了。最好的(最简单的)选择是Jep lib
jython 是长期的休眠[/dead]。这真是太糟糕了。
Derrops
Derrops
发布于 2021-07-10
0 人赞同

我认为有一些重要的事情需要首先考虑,你希望java和python之间有多强的联系。

Firstly 你是只想调用函数,还是真的想让python代码改变java对象中的数据?这一点非常重要。如果你只想调用一些有参数或无参数的python代码,那么这并不是很困难。如果你的参数是原语,那就更容易了。然而,如果你想让java类在python中实现成员函数,从而改变java对象的数据,那么这就不是那么容易或直接的了。

Secondly 我们是在讨论cpython还是jython?我想说cpython是它的优势所在!我主张这就是为什么Python是如此酷的原因!拥有如此高的抽象性,但是在需要的时候却可以使用c,c++。想象一下,如果你在java中也能做到这一点的话。这个问题甚至不值得问,如果jython可以的话,因为它很容易。

所以我玩了以下方法,并从易到难列出。

从Java到Jython

优势。 这很简单。拥有对java对象的实际引用

劣势。 No CPython, Extremely Slow!

Jython来自java,非常容易,如果这真的足够,那就太好了。但是它非常慢,而且没有cpython!没有cpython,生活还有意义吗?你可以很容易地让python代码为你的java对象实现成员函数。

从Java到Jython to CPython via Pyro

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(就像黑猩猩)来做面包之前,有很多重要的事情需要考虑。首先,如果你的解释器崩溃了,那么你的程序就完蛋了。还有,不要让我开始考虑并发性的问题。此外,还有很多很多的锅炉,我相信我已经找到了最好的配置来减少这些锅炉,但它仍然是很多的!所以如何去做呢?所以,如何去做这件事。 考虑到C++是你的中间人,你的对象实际上是C++的对象!你的对象是什么?很好,你现在知道了。只要把你的对象写成你的程序是用cpp而不是java编写的,你想从两个世界访问的数据。然后你就可以使用名为swig ( http://www.swig.org/Doc1.3/Java.html ),使之能够被java访问,并编译一个dll,在java中调用System.load(dll name here)。先把这个工作做好,然后再进入困难的部分! 为了进入python,你需要嵌入一个解释器。首先我建议做一些Hello解释器程序或这个教程 Embedding python in C/C .一旦你有了这个工作,是时候让马和猴子跳舞了!你可以通过[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,并且只使用共享库(dlls),否则boost就会出现撕裂。是的,我知道。有很多方法可以让事情变糟。所以要确保你把每一件事都逐块完成。然后把它们放在一起。

这里有一个库,可以让你一次性写好你的Python脚本,并在运行时决定使用哪种集成方法(Jython、通过Jep的CPython和Py4j)。 github.com/subes/invesdwin-context-python 由于每种方法都有自己的好处/缺点
@subes那个项目看起来很不错,我不久前写过这个。我鼓励你写一个答案,我会给它加分。我不喜欢上面的答案,哈哈,因为我认为它在谷歌搜索之外没有提供多少有用的信息。
我创建了一个单独的答案
这个答案是否有 "这应该是公认的答案 "的味道,还是只是我的问题?)
Peiming Hu
Peiming Hu
发布于 2021-07-10
0 人赞同

将python代码放在java里是不聪明的。用flask或其他网络框架来包装你的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

stx
+1 ,但在两端创建和解析来回信息的额外性能和通信开销怎么办?
是的,这需要定义一个具有最小输入/输出要求的api接口。在网络上的客户端/服务器之间有大量的数据传输是不聪明的。如果你不能定义这样一个接口,那么这种设计方法就不适合。
bsteffen
bsteffen
发布于 2021-07-10
0 人赞同

有几个答案提到,你可以使用JNI或JNA来访问cpython,但我不建议从头开始,因为已经有开源的库可以从java访问cpython。比如说。

Wildhammer
Wildhammer
发布于 2021-07-10
0 人赞同

谷德维姆 (GraalVM) is a good choice. I've done Java+Javascript combination with 谷德维姆 (GraalVM) for microservice design (Java with Javascript reflection). They recently added support for python, I'd give it a try especially with how big its community has grown over the years.

2021年6月更新

https://www.graalvm.org/reference-manual/python/

谷德维姆 (GraalVM) provides a Python 3.8 compliant runtime. A primary goal of the 谷德维姆 (GraalVM) Python runtime is to support SciPy and its constituent libraries, as well as to work with other data science and machine learning libraries from the rich Python ecosystem. At this point, the Python runtime is made available for experimentation and curious end-users.

subes
subes
发布于 2021-07-10
0 人赞同

这里有一个库,可以让你一次性写好你的Python脚本,并在运行时决定使用哪种集成方法(Jython、CPython/PyPy通过Jep和Py4j)。

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

因为每种方法都有自己的好处/缺点,正如链接中解释的那样。
(3 modules: jep, Py4J, jython )

这个项目没有任何发布。
@ChristianSchlichtherle invesdwin-context-python 1.0.0版本不可用;感谢这个小宝。 github.com/loewenfels/dep-graph-releaser
项目的发布现已完成,见 github.com/invesdwin/invesdwin-context-python/issues/1 , however one should consider number of dependencies this project brings, see github.com/invesdwin/invesdwin-context-python/issues/4
Anurag Uniyal
Anurag Uniyal
发布于 2021-07-10
0 人赞同

这取决于你所说的Python函数是什么意思? 如果它们是用 cpython 你不能直接打电话给他们,你必须使用 JNI , but if they were written in Jython 你可以很容易地从java中调用它们,因为jython最终会生成java的字节代码。

现在,当我说用cpython或jython写的时候,并没有什么意义,因为python就是python,大多数代码都可以在两种实现上运行,除非你使用依赖于cpython或java的特定库。

see here 如何在Java中使用Python解释器。

Timo
Timo
发布于 2021-07-10
0 人赞同

Depending on your requirements, options like XML-RPC 可能是有用的,它可以用来远程调用任何支持协议的语言中的函数。

15年前,我在一个项目中使用了这个方法,它复杂得要命。 至少要用JSON。
alex
alex
发布于 2021-07-10
0 人赞同

Jython有一些限制。

这其中有一些区别。首先,Jython程序不能使用用C语言编写的CPython扩展模块。 扩展模块。这些模块的文件扩展名通常为 扩展名为.so、.pyd或.dll。如果你想使用这样的模块,你应该寻找 找一个用纯Python或Java编写的同等模块。尽管在技术上 支持这样的扩展在技术上是可行的--IronPython就是这样做的--但目前还没有计划在Jython中这样做。 但没有计划在Jython中这样做。

用Jython将我的Python脚本作为JAR文件发布?

你可以简单地使用Runtime或ProcessBuilder从Java调用Python脚本(或bash或Perl脚本),并将输出传回Java。

在java中运行一个bash shell脚本

在Java中运行命令行

java runtime.getruntime() 获得执行命令行程序的输出结果

nidhin
nidhin
发布于 2021-07-10
0 人赞同