从Python调用Java

时间:2010-09-06 15:19:25

标签: java python

从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是一个死的项目吗?

还有其他选择吗?

此致 大卫

9 个答案:

答案 0 :(得分:123)

您也可以使用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的作者

答案 1 :(得分:40)

以下是我对此问题的总结:5种从Python调用Java的方法

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

简短回答:Jpype工作得很好并且在许多项目中得到证明(例如python-boilerpipe),但Pyjnius比JPype更快更简单

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

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

答案 2 :(得分:16)

Pyjnius。

文档:http://pyjnius.readthedocs.org/en/latest/

Github:https://github.com/kivy/pyjnius

从github页面:

  

使用JNI以Python类访问Java类的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 :(得分:5)

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

使用Jnius(others have too)进入安装问题,安装Javabridge但在我尝试使用它时出现了神秘的错误,PyJ4不得不首先用Java启动网关服务器,JCC不会这样做。安装。最后,JPype最终工作了。在Github上有maintained fork of 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路径(否则你将无法理解"类找不到"错误)。对我来说,这意味着将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 :(得分:4)

如果您使用的是Python 3,那么有一个名为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()

答案 5 :(得分:2)

我刚刚开始使用JPype 0。5。4。2(2011年7月),它看起来效果很好......
我正在使用Xubuntu 10.04

答案 6 :(得分:2)

我最近在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和Linux?

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

答案 7 :(得分:1)

我假设如果你可以从C ++到Java,那么你就完全了。我见过你提到的那种产品很好用。碰巧我们使用的是CodeMesh。我不是特别赞同这个供应商,或者对他们产品的相对质量作出任何陈述,但我已经看到它在相当高的情况下工作。

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

答案 8 :(得分:0)

根据我自己的经验,尝试从python中运行一些java代码,类似于python代码在python中的java代码中运行的方式,我无法找到一个简单的方法。

我的问题的解决方案是在使用适当的包和变量编辑临时文件中的java代码之后,通过从我的python代码中调用beanshell解释器作为shell commnad来运行这个java代码作为beanshell脚本。

如果我所谈论的内容有任何帮助,我很乐意帮助您分享我的解决方案的更多细节。