我想知道是否可以使用Jython从Java代码中调用Python函数,还是只能用于从Python中调用Java代码?
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。
PyObject obj = interpreter.compile("..."); // 一段包含两个函数 myFunc1 和 myFunc2 的代码,如何调用指定的函数,例如 myFunc1
- soulmachine我认为在你希望Java和Python之间的链接有多强大时,首先需要考虑一些重要的事情。
首先,你只想调用函数还是实际上希望Python代码改变Java对象中的数据?这非常重要。如果你只想调用一些带或不带参数的Python代码,那就不太困难。如果你的参数是基本类型,那就更容易了。然而,如果你希望Java类在Python中实现成员函数,并改变Java对象的数据,那么这就不那么容易或直接了。
其次,我们讨论的是CPython还是Jython?我会说CPython才是王道!我会主张这正是Python如此酷的原因!它具有如此高的抽象性,但在需要时可以访问C或C++。想象一下,如果你能在Java中做到这一点。如果Jython可以的话,这个问题甚至不值得提问,因为那样很容易。
所以我尝试了以下几种方法,并按照从简单到困难的顺序列出:
Java到Jython
优点:非常简单。可以实际引用Java对象。
缺点:没有CPython,非常慢!
Jython从Java转换非常简单,如果这已经足够了,那太好了。然而它非常慢,没有CPython!没有CPython的生活还有意义吗?我不这么认为!你可以轻松地使用Python代码来实现你的Java对象的成员函数。通过JNI/JNA/SWIG将Java转换为C/C++,再通过嵌入式解释器将其转换为Python(可能使用BOOST库?)
OMG这个方法可不是给胆小鬼用的。我可以告诉你,我花了很长时间才找到一个合适的方法来实现这个。你想要这样做的主要原因是为了能够运行CPython代码,让它完全控制你的Java对象。在决定尝试将Java(就像一只黑猩猩)和Python(就像一匹马)结合起来之前,有几个重要的事情需要考虑。首先,如果解释器崩溃了,你的程序就完蛋了!别让我再提并发问题了!此外,还有很多琐碎的东西,我相信我已经找到了最佳配置来最小化这些琐碎的东西,但仍然有很多!那么如何开始呢: 首先要知道C++是你的中间人,你的对象实际上是C++对象!很高兴你现在知道了这一点。只需将你的对象编写得好像你的程序是用C++而不是Java编写的,包括你想从两个世界访问的数据。然后,你可以使用名为SWIG的包装生成器,使其对Java可访问,并编译一个dll,在Java中调用该dll(System.load(dllNameHere)
)。首先确保这个工作正常,然后再进行下一步!
要进入Python,你需要嵌入一个解释器。首先,我建议你做一些简单的解释器程序或者参考这个教程Embedding Python in C/C。一旦你搞定了这个,就是让马和猴子跳舞的时候了!你可以通过[boost][3]将你的C++对象发送到Python中。我知道我没有给你鱼,只是告诉你在哪里找到鱼。在编译时,请注意以下几点。将Python代码嵌入Java程序并不明智。使用Flask或其他Web框架将Python代码封装成微服务,这样您的Java程序就可以调用该微服务(例如通过REST)。
这种方法简单易行,能够避免大量问题的发生。而且代码松散耦合,易于扩展。
2020年3月24日更新: 根据@stx的评论,上述方法不适用于客户端和服务器之间的大量数据传输。 以下是我推荐的另一种方法:使用Rust(C/C++也可)连接Python和Java。 https://medium.com/@shmulikamar/https-medium-com-shmulikamar-connecting-python-and-java-with-rust-11c256a1dfb0
GraalVM是一个很好的选择。我曾经使用GraalVM进行Java+Javascript的微服务设计(Java与Javascript反射)。他们最近增加了对Python的支持,尤其是考虑到它在过去几年中社区的规模已经变得非常大,我觉得可以试一试。
2021年6月更新:
https://www.graalvm.org/reference-manual/python/中提到:
GraalVM提供符合Python 3.8标准的运行环境。GraalVM Python运行时的主要目标是支持SciPy及其组成库,并且能够与来自Python生态系统的其他数据科学和机器学习库一起工作。当前阶段,Python运行时可供实验和好奇的终端用户使用。
这里有一个库,可以让你编写一次Python脚本,并在运行时决定使用哪种集成方法(通过 Jep 和 Py4j 的 CPython/PyPy、Jython):
https://github.com/subes/invesdwin-context-python
由于每种方法都有其自己的优缺点,如链接中所述。
(3个模块:jep、Py4J、jython)
根据您的需求,像XML-RPC这样的选项可能会很有用,它可以用于远程调用支持该协议的任何语言中的函数。
您可以使用Java Native Interface从Java调用任何语言。