在 Java 中调用 Python?

Posted

技术标签:

【中文标题】在 Java 中调用 Python?【英文标题】:Calling Python in Java? 【发布时间】:2012-02-12 12:01:49 【问题描述】:

我想知道是否可以使用jython从java代码调用python函数,还是只能从python调用java代码?

【问题讨论】:

请查看类似问题并阅读答案。 bytes.com/topic/python/answers/… 【参考方案1】:

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 中 如果没有错误它会起作用,所以显然不是这样;)“错误”并不意味着运行时错误,也可能是编译错误。 Python 2 的生命周期为 1.1.2020,Jython 仅支持 Python 2.7。所以没有 Jython 基本上是死的。最好(最简单)的选项是 Jep lib jython 长期处于休眠状态 [/dead]。太糟糕了。【参考方案2】:

我认为首先要考虑一些重要的事情,即您希望在 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.util 中看到这些更改。你只需要记住从 pyro 发回你想要的数据。我相信这是进入 cpython 的最简单方法!你不需要任何 jni 或 jna 或 swig 或.... 你不需要知道任何 c 或 c++。酷啊?

优点:接触cpython,没有以下方法那么难

缺点: 无法直接从 python 中更改 java 对象的成员数据。有点间接,(jython 是中间人)。

Java 到 C/C++ 通过 JNI/JNA/SWIG 到 Python 通过嵌入式解释器(可能使用 BOOST 库?)

天哪,这种方法不适合胆小的人。我可以告诉你,我花了很长时间才用一种体面的方法实现这一目标。您想要这样做的主要原因是您可以运行 cpython 代码来完全控制您的 java 对象。在决定尝试用 python(就像一匹马)和面包 java(就像黑猩猩)之前,有一些主要的事情需要考虑。首先,如果您崩溃了为您的程序熄灯的解释器!不要让我开始处理并发问题!另外,还有allot allot of 锅炉,我相信我已经找到了最小化这个锅炉的最佳配置,但它仍然是allot!那么如何解决这个问题: 考虑到 C++ 是你的中间人,你的对象实际上是 C++ 对象!很好,你现在知道了。只需编写您的对象,就好像您的程序在 cpp 而不是 java 中一样,使用您想要从两个世界访问的数据。然后,您可以使用名为 swig (http://www.swig.org/Doc1.3/Java.html) 的包装器生成器使 java 可以访问它,并在 java 中编译一个您称为 System.load(dll name here) 的 dll。先完成这项工作,然后再进行最困难的部分! 要使用 python,您需要嵌入解释器。首先我建议做一些你好解释程序或本教程Embedding python in C/C。一旦你完成了这项工作,就该让马和猴子跳舞了!您可以通过 [boost][3] 将 c++ 对象发送到 python。我知道我没有给你鱼,只是告诉你在哪里可以找到鱼。编译时需要注意的一些指针。

当你编译 boost 时,你需要编译一个共享库。并且您需要包含并链接到 jdk 所需的内容,即 jvm.lib、jvm.lib(启动应用程序时您的路径中还需要客户端 jvm.dll)以及 python27.lib 或不管和 boost_python-vc100-mt-1_55.lib。 然后包含 Python/include、jdk/include、boost 并仅使用共享库 (dll),否则 boost 会让人哭笑不得。是的,我知道。有很多方法可以使这变酸。因此,请确保您逐块完成每件事。然后把它们放在一起。

【讨论】:

这里有一个库,可让您编写一次 Python 脚本并决定在运行时使用哪种集成方法(Jython、CPython via Jep 和 Py4j):github.com/subes/invesdwin-context-python 因为每种方法都有其自身的优点/缺点 @subes 那个项目看起来棒极了我不久前写的。我鼓励你写一个我会赞成的答案。我不喜欢最佳答案哈哈,因为我认为它在谷歌搜索之外没有提供太多有用的信息。 我创建了一个单独的答案 这个答案闻起来是“这应该是公认的答案”还是只有我? ;-)【参考方案3】:

在 java 中包含 python 代码并不聪明。用烧瓶或其他 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

【讨论】:

+1 ,但是在两端来回创建和解析消息的额外性能和通信开销呢? 是的,这需要定义一个需要最少输入/输出的api接口。在网络上的客户端/服务器之间进行大量数据传输是不明智的。如果你不能定义这样的接口,那么这种设计方法就不适合了。【参考方案4】:

一些答案​​提到您可以使用 JNI 或 JNA 来访问 cpython,但我不建议从头开始,因为已经有用于从 java 访问 cpython 的开源库。例如:

JEP JPY

【讨论】:

【参考方案5】:

GraalVM 是个不错的选择。我已经将 Java+javascript 与 GraalVM 结合用于微服务设计(Java 与 Javascript 反射)。他们最近增加了对 python 的支持,我会试一试,尤其是随着它的社区多年来的发展。

2021 年 6 月更新

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

GraalVM 提供兼容 Python 3.8 的运行时。 GraalVM Python 运行时的主要目标是支持 SciPy 及其组成库,以及与来自丰富 Python 生态系统的其他数据科学和机器学习库一起使用。此时,Python 运行时可供实验和好奇的最终用户使用。

【讨论】:

【参考方案6】:

这里有一个库,可让您编写一次 Python 脚本并决定在运行时使用哪种集成方法(Jython、CPython/PyPy via Jep 和 Py4j):

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

由于每种方法都有其自身的优点/缺点,如链接中所述。 (3个模块:jep、Py4J、jython)

【讨论】:

这个项目没有任何版本。 @ChristianSchlichtherle invesdwin-context-python 1.0.0 版不可用;感谢这个小宝石:github.com/loewenfels/dep-graph-releaser 项目发布现已发布,请参阅github.com/invesdwin/invesdwin-context-python/issues/1,但应考虑此项目带来的依赖项数量,请参阅github.com/invesdwin/invesdwin-context-python/issues/4【参考方案7】:

这取决于你所说的python函数是什么意思?如果它们是用cpython 编写的,你不能直接调用它们,你必须使用JNI,但是如果它们是用Jython 编写的,你可以很容易地从java 调用它们,因为jython 最终会生成java 字节码。

现在,当我说用 cpython 或 jython 编写时,它没有多大意义,因为 python 是 python,并且大多数代码将在这两种实现上运行,除非您使用依赖于 cpython 或 java 的特定库。

看这里how to use Python interpreter in Java.

【讨论】:

【参考方案8】:

根据您的要求,XML-RPC 之类的选项可能很有用,可用于远程调用支持协议的任何语言的虚拟函数。

【讨论】:

我在 15 年前的一个项目中使用了它,它非常复杂。至少使用 JSON..【参考方案9】:

你可以使用Java Native Interface从java调用任何语言

【讨论】:

任何本身可以从 c 调用的语言。好吧,python 可以,但是 Jython 确实是一个更简单的解决方案(或者在 j6+ 中使用 PyInterpreter)。编写代码从 c 调用 python 函数并不是那么简单。【参考方案10】:

Jython 有一些限制:

有许多不同之处。一、Jython程序不能使用CPython 用 C 编写的扩展模块。这些模块通常有文件 扩展名 .so、.pyd 或 .dll。如果你想使用这样的模块,你应该看看 对于用纯 Python 或 Java 编写的等价物。虽然在技术上 支持此类扩展是可行的 - IronPython 这样做 - 没有计划 在 Jython 中这样做。

Distributing my Python scripts as JAR files with Jython?

您可以简单地使用 Runtime 或 ProcessBuilder 从 Java 调用 python 脚本(或 bash 或 Perl 脚本)并将输出传递回 Java:

Running a bash shell script in java

Running Command Line in Java

java runtime.getruntime() getting output from executing a command line program

【讨论】:

【参考方案11】:

This 很好地概述了当前选项。其中一些在其他答案中被命名。在他们决定实现 Python 3.x 之前,Jython 不可用,并且许多其他项目都来自 python 端并想要访问 java。但是仍然有一些选择,可以命名尚未命名的东西:gRPC

【讨论】:

这回答了***.com/questions/67820680/…。谢谢【参考方案12】:

我有类似的需求,我认为最好的解决方案是 thrift 对我来说(也是一个 rpc 解决方案),现在只需运行测试成功通过,并且可以使用 thrift-generator 从 java 接口生成 thrift 文件,然后生成 python thrift 文件中的文件和 java 客户端文件

【讨论】:

以上是关于在 Java 中调用 Python?的主要内容,如果未能解决你的问题,请参考以下文章

如何在Java中调用Python代码

如何在Java中调用Python代码

java调用python方法及常用的java调用python代码

教你如何在Spark Scala/Java应用中调用Python脚本

java调用python接口详解

java调用python接口详解