从 Python 调用 Java

从 python 调用 java 的最佳方法是什么? (jython 和 RPC 对我来说不是一个选项)。

我听说过 JCC: 一个 http://pypi.python.org/pypi/JCC/1.9 一个用于从 C + +/Python 调用 Java 的 C + + 代码生成器 但是这需要编译每个可能的调用; 我更喜欢另一种解决方案。

我听说过 JPype: 一个 http://JPype.sourceforge.net/ 教程: < a href = “ http://www.slideshare.net/onyame/mix-python-and-java”rel = “ norefrer”> http://www.slideshare.net/onyame/mixing-python-and-java

import jpype
jpype.startJVM(path to jvm.dll, "-ea")
javaPackage = jpype.JPackage("JavaPackageName")
javaClass = javaPackage.JavaClassName
javaObject = javaClass()
javaObject.JavaMethodName()
jpype.shutdownJVM()

这看起来就是我需要的。 然而,最后一次发布是在2009年1月,我看到人们无法编译 JPype。

JPype 是一个死项目吗?

还有其他选择吗?

224155 次浏览

我假设,如果你能从 C + + 到 Java,那么你就已经准备好了。我见过你提到的那种产品,效果很好。碰巧我们用的是 CodeMesh。我并没有特别支持这个供应商,也没有对他们的产品的相对质量做任何声明,但我看到它在一个相当大的产量场景中工作。

我一般会说,如果可能的话,我建议尽量避免通过 JNI 进行直接集成。一些简单的 REST 服务方法或基于队列的体系结构往往更易于开发和诊断。如果谨慎地使用这种解耦技术,您可以获得相当不错的性能。

根据我自己的经验,我试图在 python 中运行一些 java 代码,其方式类似于 python 代码在 python 中的 java 代码中的运行方式,但我无法找到一种直截了当的方法。

我解决这个问题的方法是,在用适当的包和变量编辑临时文件中的 Java 代码之后,从我的 python 代码中将 BeanShell 解释器作为 shell 命令调用,从而将这段 Java 代码作为 BeanShell 脚本运行。

如果我所说的在任何方面都有帮助,我很高兴能帮助你们分享我的解决方案的更多细节。

您也可以使用 Py4J。首页上有一个示例和大量文档,但本质上,您只需从 Python 代码中调用 Java 方法,就好像它们是 python 方法一样:

from py4j.java_gateway import JavaGateway
gateway = JavaGateway()                        # connect to the JVM
java_object = gateway.jvm.mypackage.MyClass()  # invoke constructor
other_object = java_object.doThat()
other_object.doThis(1,'abc')
gateway.jvm.java.lang.System.out.println('Hello World!') # call a static method

与 Jython 不同,Py4J 的一部分是在 Python VM 中运行的,所以它总是与最新版本的 Python 保持“最新”,并且您可以使用在 Jython 上运行不好的库(例如 lxml)。另一部分运行在要调用的 JavaVM 中。

通信是通过套接字而不是 JNI 完成的,Py4J 有自己的协议(优化某些情况,管理内存,等等)

免责声明: 我是 Py4J 的作者

我刚刚开始使用 JPype 0.5.4.2(2011年7月) ,它看起来工作得很好..。
我用的是 Xubuntu 10.04

Pyjnius 医生Github

来自 github 页面:

使用 JNI 将 Java 类作为 Python 类访问的 Python 模块。

PyJNIus 是一个“在进行中的工作”。

快速概述

>>> from jnius import autoclass
>>> autoclass('java.lang.System').out.println('Hello world')
Hello world


>>> Stack = autoclass('java.util.Stack')
>>> stack = Stack()
>>> stack.push('hello')
>>> stack.push('world')
>>> print stack.pop()
world
>>> print stack.pop()
hello

下面是我对这个问题的总结: 从 Python 调用 Java 的5种方法

Http://baojie.org/blog/2014/06/16/call-java-from-python/ (缓存)

简短的回答: JPype 工作得非常好,并且在许多项目中得到了证明(比如 python-boilertube) ,但是 Pyjnius 比 JPype 更快、更简单

我试过 Pyjnius/Jnius、 JCC、 javabridge、 Jpype 和 Py4j。

Py4j 有点难用,因为您需要启动一个网关,添加另一层脆弱性。

如果您使用的是 Python3,那么有一个名为 JPype1-py3的 JPype 分支

pip install JPype1-py3

这适用于我在 OSX/Python 3.4.3上的工作。(您可能需要 export JAVA_HOME=/Library/Java/JavaVirtualMachines/your-java-version)

from jpype import *
startJVM(getDefaultJVMPath(), "-ea")
java.lang.System.out.println("hello world")
shutdownJVM()

我最近一直在把很多东西集成到 Python 中,包括 Java。我发现的最健壮的方法是使用 IKVM 和 C # 包装器。

IKVM 有一个简洁的小应用程序,可以将任何 JavaJAR 直接转换为。网络 DLL。它只是将 JVM 字节码转换为 CLR 字节码。详情请参阅 http://sourceforge.net/p/ikvm/wiki/Ikvmc/

转换后的库的行为就像一个本地 C # 库,您可以使用它而不需要 JVM。然后可以创建 C # DLL 包装器项目,并添加对转换后的 DLL 的引用。

现在可以创建一些包装存根来调用要公开的方法,并将这些方法标记为 DllEport。详情请参阅 https://stackoverflow.com/a/29854281/1977538

封装器 DLL 的作用就像一个本机 C 库,导出的方法看起来就像导出的 C 方法。您可以像往常一样使用 ctype 连接到它们。

我已经在 Python 2.7中尝试过了,但它应该也可以在3.0中使用。在 Windows 和 Linux 上工作

如果您碰巧使用 C # ,那么在将几乎所有内容集成到 python 中时,这可能是最好的尝试方法。

我在 OSX 10.10.2上,成功地使用了 JPype。

在安装 Jnius (其他人也是)时遇到了问题,安装了 Javabridge,但是在我尝试使用它时出现了神秘的错误,PyJ4有这样的不便: 必须首先用 Java 启动网关服务器,JCC 不会安装。最终,JPype 成功了。Github 上有个 维护的 JPype 分支。它的主要优点是: (a)安装正确; (b)可以非常有效地将 java 数组转换为 numpy 数组(np_arr = java_arr[:])

安装过程如下:

git clone https://github.com/originell/jpype.git
cd jpype
python setup.py install

你应该能做到 import jpype

下面的演示成功了:

import jpype as jp
jp.startJVM(jp.getDefaultJVMPath(), "-ea")
jp.java.lang.System.out.println("hello world")
jp.shutdownJVM()

当我尝试调用我自己的 Java 代码时,我必须首先进行编译(javac ./blah/HelloWorldJPype.java) ,并且必须从默认值更改 JVM 路径(否则会得到无法解释的“ class not found”错误)。对我来说,这意味着将 startJVM 命令更改为:

jp.startJVM('/Library/Java/JavaVirtualMachines/jdk1.7.0_79.jdk/Contents/MacOS/libjli.dylib', "-ea")
c = jp.JClass('blah.HelloWorldJPype')
# Where my java class file is in ./blah/HelloWorldJPype.class
...