问题:从Python调用Java
从python调用Java的最佳方法是什么?(jython和RPC对我来说不是一个选择)。
我听说过JCC:http : //pypi.python.org/pypi/JCC/1.9 一个用于从C ++ / Python调用Java的C ++代码生成器,但这需要编译所有可能的调用。我希望有另一个解决方案。
我听说过JPype:http : //jpype.sourceforge.net/ 教程: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是一个死项目吗?
还有其他选择吗?
问候,大卫
回答 0
这是我对这个问题的总结:从Python调用Java的5种方法
http://baojie.org/blog/2014/06/16/call-java-from-python/(已缓存)
简短的答案:Jpype效果很好,并且在许多项目中都得到了证明(例如python-boilerpipe),但是Pyjnius比JPype更快,更简单。
我已经尝试过Pyjnius / Jnius,JCC,javabridge,Jpype和Py4j。
Py4j有点难以使用,因为您需要启动网关,从而增加了另一层脆弱性。
回答 1
您也可以使用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)。另一部分在您要调用的Java VM中运行。
通信是通过套接字而不是通过JNI进行的,并且Py4J具有自己的协议(用于优化某些情况,管理内存等)。
免责声明:我是Py4J的作者
回答 2
皮尤尼斯
文件:http : //pyjnius.readthedocs.org/en/latest/
GitHub:https : //github.com/kivy/pyjnius
从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
回答 3
我使用OSX 10.10.2,并成功使用JPype。
遇到Jnius的安装问题(其他人也有),安装了Javabridge,但是在我尝试使用它时出现了神秘的错误,PyJ4的不便之处在于必须首先在Java中启动Gateway服务器,而JCC无法安装。最终,JPype结束了工作。在Github上有一个JPype的维护分支。它的主要优点是(a)正确安装,并且(b)可以非常有效地将java数组转换为numpy array(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路径从默认值更改(否则,将出现无法解释的“找不到类”错误)。对我来说,这意味着将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
...
回答 4
如果您使用的是Python 3,则有一个JPype的分支,称为JPype1-py3
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()
回答 5
最近,我一直在将很多东西集成到Python中,包括Java。我发现的最可靠的方法是使用IKVM和C#包装器。
IKVM有一个简洁的小应用程序,它允许您使用任何Java JAR,并将其直接转换为.Net 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和Linuxes上均可使用
如果您碰巧使用C#,那么这可能是将几乎所有内容都集成到python中的最佳方法。
回答 6
我刚刚开始使用JPype 0.5.4.2(2011年7月),并且看起来工作得很好…
我使用的是Xubuntu 10.04
回答 7
我假设,如果您可以从C ++到Java,那么您已经准备就绪。我看过您提到的那种产品效果很好。碰巧我们使用的是CodeMesh。我没有特别认可该供应商,也没有对他们的产品相对质量发表任何声明,但是我看到它在相当大的情况下有效。
我通常会说,如果可能的话,我建议您尽量避免通过JNI直接集成。一些简单的REST服务方法或基于队列的体系结构将更易于开发和诊断。如果仔细使用这样的去耦技术,您将获得相当不错的性能。
回答 8
根据我自己的经验,尝试从python ia中运行某些Java代码的方式类似于在python中的Java代码中运行python代码的方式,我无法找到一种简单的方法。
我对问题的解决方案是通过在具有适当包和变量的临时文件中编辑Java代码后,通过从python代码中将beanshell解释程序作为shell commnad调用,将此Java代码作为beanshell脚本运行。
如果我在说什么对您有任何帮助,很高兴能帮助您分享我的解决方案的更多详细信息。