2009-01-13 60 views
10

我有一个python程序,它在CPython实现上运行,在它里面我必须调用一个在java程序中定义的函数。我怎样才能做到这一点?如何从CPython调用java对象和函数?

如果能够使用一些java对象也不错。

Jython不是一个选项。我必须在CPython中运行python部分。

回答

9

最简单的事情是

  1. 写一个简单的CLI为您的Java “功能”。 (有没有这样的事情,所以我会假设你实际上意味着一个Java类的方法函数。)

    public class ExposeAMethod { 
        public static void main(String args[]) { 
         TheClassToExpose x = new TheClassToExpose(); 
         x.theFunction(); 
        } 
    } 
    
  2. 编译和构建这个可执行的JAR文件的入口点。调用它 ExposeAMethod.jar

  3. 从子流程创建的命令中调用它。

    import subprocess 
    p = subprocess.Popen("java -jar ExposeAMethod.jar", shell=True) 
    sts = os.waitpid(p.pid, 0) 
    

这是起码的。实际上并不多。我计算了6行java,3行Python,然后启动并运行。

如果要将参数传递给此Java类构造函数或方法函数,则必须再写几行代码。你有两个选择。

  • 从标准输入读取参数,将结果写入标准输出。这是相对容易的,表现非常好。

  • 将参数解析为Java的命令行选项,将结果写入stdout。这稍微困难一些,但总的来说非常好。奖金是,你现在有一个有用的命令行Java程序,你可以重用。

1

我不知道Python的,上次我不得不从C应用程序(NT服务)调用Java我不得不加载jvm.dll。看看JNI文档。

另外,如果你不关心性能,你总是调用os.system(“java com.myapp.MyClass”)。

7

如果你不想去写你自己的JNI/C路线。

另一种选择是使用jpype,对我来说总是用来访问Oracle数据库,因为在PC上安装oracle c驱动程序是一种皮塔饼。 你可以不喜欢的东西(从文档):

from jpype import * 
startJVM("d:/tools/j2sdk/jre/bin/client/jvm.dll", "-ea") # or path to your jvm 
java.lang.System.out.println("hello world") 
shutdownJVM() 

它已经有一段时间没有更新了,并没有太多的文档的方式,但它确实工作得相当好。

+0

链接转到过时的版本。在这里找到正确的:https://pypi.python.org/pypi/JPype1 https://github.com/originell/jpype和这里的文档:https://jpype.readthedocs.io/en/latest/ – bastian 2017-01-21 09:59:54

13

道歉复活线程,但我想我有:-)

一个更好的答案你也可以使用Py4J有两个部分:一个库运行在CPython(或任何Python解释器)和一个运行在您想调用的Java VM上的库中。

上有FrontPage和大量的文件的例子,但本质上,你只需要调用从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 

的通信是通过插座而不是做JNI。

免责声明:我Py4J

+0

使用套接字有什么好处?它不是比JNI慢吗?你有性能统计数据吗? – bastian 2017-01-21 10:01:54

+1

JNI肯定会有更少的开销!虽然(JNI在Windows上并不总是有趣),但套接字更具可移植性,并支持更多的场景(例如,与JVM不同的机器上的Python解释器)。 – Barthelemy 2017-01-23 21:40:06

1

看看笔者在我们的项目python-javabridge。这是一个围绕JNI的Python包装,由CellProfiler大量使用。它提供对JNI的低级访问和对Java对象的高级反射访问。