当前位置: 首页 > 面试题库 >

如何从python / numpy调用Java函数?

韩琛
2023-03-14
问题内容

我很清楚如何用C ++扩展Python,但是如果我想用Java编写要与numpy一起使用的函数怎么办?

这是一个简单的场景:我想使用Java类来计算numpy数组的平均值。如何将numpy向量传递给Java类并收集结果?

谢谢你的帮助!


问题答案:

我花了一些时间回答自己的问题,并希望分享我的答案,因为我觉得关于 stackoverflow的
这个主题的信息不多。我还认为,由于Java的性能和其他良好的软件开发功能的改进,Java将在科学计算中变得更加重要(例如,请参见WEKA软件包进行数据挖掘)。

总的来说,事实证明,使用正确的工具,用Java扩展Python比使用C / C ++容易得多!

  • http://pypi.python.org/pypi/JCC:由于没有适当的文档,此工具无用。

  • Py4J:需要在使用python之前启动Java进程。正如其他人所说,这可能是失败的地方。而且,没有记录使用的很多例子。

  • JPype:虽然发展似乎是死亡,它运作良好,并有在网络上就可以了许多实例(例如,见http://kogs-www.informatik.uni-hamburg.de/~meine/weka-python/使用用Java编写的数据挖掘库)。因此, 我决定专注于此工具

在Fedora 16上安装JPype

我正在使用Fedora
16,因为在Linux上安装JPype时会遇到一些问题,因此我将介绍我的方法。下载JPype,然后在第48行中通过提供JDK路径来修改
setup.py 脚本:

self.javaHome = '/usr/java/default'

然后运行:

sudo python setup.py install

成功安装后,请检查以下文件:

/usr/lib64/python2.7/site-packages/jpype/_linux.py

并将方法 getDefaultJVMPath() 删除或重命名为 getDefaultJVMPath_old() ,然后添加以下方法:

def getDefaultJVMPath():
    return "/usr/java/default/jre/lib/amd64/server/libjvm.so"

替代方法 :不要在上面的文件 __linux.py中_
进行任何更改,但不要使用getDefaultJVMPath()方法(或调用此方法的方法)。在使用 getDefaultJVMPath()
的位置,直接提供JVM的路径。请注意,有几个路径,例如,在我的系统中,我还具有以下路径,它们引用了不同版本的JVM(尚不清楚客户端JVM还是服务器JVM更适合我):

  • /usr/lib/jvm/java-1.5.0-gcj-1.5.0.0/jre/lib/x86_64/client/libjvm.so
  • /usr/lib/jvm/java-1.5.0-gcj-1.5.0.0/jre/lib/x86_64/server/libjvm.so
  • /usr/lib/jvm/java-1.6.0-openjdk-1.6.0.0.x86_64/jre/lib/amd64/server/libjvm.so

最后, 将以 下行添加到 〜/ .bashrc中 (或在每次打开python解释器之前都运行它):

export JAVA_HOME='/usr/java/default'

(上面的目录实际上只是到我的最新JDK版本的符号链接,该版本位于 /usr/java/jdk1.7.0_04 )。

请注意,已下载JPype的目录中的所有测试(即 JPype-0.5.4.2 / test / testsuite.py) 都将失败(因此请不要在意)。

要查看它是否有效,请在python中测试此脚本:

import jpype 
jvmPath = jpype.getDefaultJVMPath() 
jpype.startJVM(jvmPath)
# print a random text using a Java class
jpype.java.lang.System.out.println ('Berlusconi likes women') 
jpype.shutdownJVM()

也使用Numpy从Java调用Java类

让我们开始实现一个Java类,其中包含一些我想应用于 numpy arrays的
函数。由于没有状态的概念,因此我使用静态函数,因此不需要创建任何Java对象(创建Java对象不会改变任何内容)。

/**
 * Cookbook to pass numpy arrays to Java via Jpype
 * @author Mannaggia
 */

package test.java;

public class Average2 {

public static double compute_average(double[] the_array){
    // compute the average
    double result=0;
    int i;
    for (i=0;i<the_array.length;i++){
        result=result+the_array[i];
    }
    return result/the_array.length;
}
// multiplies array by a scalar
public static double[] multiply(double[] the_array, double factor) {

    int i;
    double[] the_result= new double[the_array.length];
    for (i=0;i<the_array.length;i++) {
        the_result[i]=the_array[i]*factor;
    }
    return the_result;
}

/**
 * Matrix multiplication. 
 */
public static double[][] mult_mat(double[][] mat1, double[][] mat2){
    // find sizes
    int n1=mat1.length;
    int n2=mat2.length;
    int m1=mat1[0].length;
    int m2=mat2[0].length;
    // check that we can multiply
    if (n2 !=m1) {
        //System.err.println("Error: The number of columns of the first argument must equal the number of rows of the second");
        //return null;
        throw new IllegalArgumentException("Error: The number of columns of the first argument must equal the number of rows of the second");
    }
    // if we can, then multiply
    double[][] the_results=new double[n1][m2];
    int i,j,k;
    for (i=0;i<n1;i++){
        for (j=0;j<m2;j++){
            // initialize
            the_results[i][j]=0;
            for (k=0;k<m1;k++) {
                the_results[i][j]=the_results[i][j]+mat1[i][k]*mat2[k][j];
            }
        }
    }
    return the_results;
}

/**
 * @param args
 */
public static void main(String[] args) {
    // test case
    double an_array[]={1.0, 2.0,3.0,4.0};
    double res=Average2.compute_average(an_array);
    System.out.println("Average is =" + res);
}
}

该类的名称有点令人误解,因为我们不仅旨在计算numpy向量的平均值(使用方法 compute_average ),而且还将numpy向量与标量 相乘
(方法 乘法 ),最后将矩阵相乘乘法(方法 mult_mat )。

编译完上述Java类之后,我们现在可以运行以下Python脚本

import numpy as np
import jpype

jvmPath = jpype.getDefaultJVMPath() 
# we to specify the classpath used by the JVM
classpath='/home/mannaggia/workspace/TestJava/bin'
jpype.startJVM(jvmPath,'-Djava.class.path=%s' % classpath)

# numpy array
the_array=np.array([1.1, 2.3, 4, 6,7])
# build a JArray, not that we need to specify the Java double type using the jpype.JDouble wrapper
the_jarray2=jpype.JArray(jpype.JDouble, the_array.ndim)(the_array.tolist())
Class_average2=testPkg.Average2 
res2=Class_average2.compute_average(the_jarray2)
np.abs(np.average(the_array)-res2) # ok perfect match!

# now try to multiply an array
res3=Class_average2.multiply(the_jarray2,jpype.JDouble(3))
# convert to numpy array
res4=np.array(res3) #ok

# matrix multiplication
the_mat1=np.array([[1,2,3], [4,5,6], [7,8,9]],dtype=float)
#the_mat2=np.array([[1,0,0], [0,1,0], [0,0,1]],dtype=float)
the_mat2=np.array([[1], [1], [1]],dtype=float)
the_mat3=np.array([[1, 2, 3]],dtype=float)

the_jmat1=jpype.JArray(jpype.JDouble, the_mat1.ndim)(the_mat1.tolist())
the_jmat2=jpype.JArray(jpype.JDouble, the_mat2.ndim)(the_mat2.tolist())
res5=Class_average2.mult_mat(the_jmat1,the_jmat2)
res6=np.array(res5) #ok

# other test
the_jmat3=jpype.JArray(jpype.JDouble, the_mat3.ndim)(the_mat3.tolist())
res7=Class_average2.mult_mat(the_jmat3,the_jmat2)
res8=np.array(res7)
res9=Class_average2.mult_mat(the_jmat2,the_jmat3)
res10=np.array(res9)

# test error due to invalid matrix multiplication
the_mat4=np.array([[1], [2]],dtype=float)
the_jmat4=jpype.JArray(jpype.JDouble, the_mat4.ndim)(the_mat4.tolist())
res11=Class_average2.mult_mat(the_jmat1,the_jmat4)

jpype.java.lang.System.out.println ('Goodbye!') 
jpype.shutdownJVM()


 类似资料:
  • 问题内容: 我正在做一个网络抓取项目。我正在使用的网站之一的数据来自Javascript。 在我之前的一个问题中,有人建议我可以直接从Python调用Javascript,但是我不确定如何实现。 例如:如果JavaScript函数定义为: 如何从Python调用JavaScript函数? 问题答案: 查找具有Python绑定的JavaScript解释器。(尝试Rhino?V8?SeaMonkey?

  • 问题内容: 我需要从Java调用C#函数,为此,我创建了以下代码。我有一个创建的Java头文件Authenticator.h,代码如下: 然后,我创建了一个身份验证的C#函数 然后,我尝试使用以下代码从C ++(项目创建dll)中调用C#函数; 最后创建一个需要从Java调用的dll。该dll已创建,并且可以在Java中很好地加载它,但是在Java中却收到此错误日志。我可能会错过什么。 问题答案:

  • 问题内容: 如何从C ++应用程序调用Java函数? 我知道从CMD(或类似技术)调用它们的方法,但我宁愿不使用它们。 问题答案: 例如,检查从C创建JVM。它显示了创建JVM和调用方法的示例过程。如果JVM已经存在;例如,您的C程序被Java程序调用(回调情况),则可以缓存JNIEnv *指针。 作为建议,请小心从C / C ++缓存指向JVM的指针,其中涉及到一些有关可以缓存的内容的语义,以后

  • 问题内容: 是否可以从Javascript调用Java(GWT)方法?从文档中也不清楚。http://code.google.com/intl/zh- CN/webtoolkit/doc/latest/DevGuideCodingBasicsJSNI.html上的 所有示例都演示了如何从JSNI(而非JS)函数调用Java函数。 更新1 这是一个Java代码: 这是html中的呼叫者按钮示例: 这

  • 本文向大家介绍我们如何从MATLAB调用Python函数?,包括了我们如何从MATLAB调用Python函数?的使用技巧和注意事项,需要的朋友参考一下 Python库现已在MATLAB中提供(自2014b起)。如果我们使用的是2014b或更高版本,则可以直接在MATLAB中运行代码。 这样就可以在MATLAB中使用python模块。无需进行任何其他更改,只需在要使用的python库名称之前添加“

  • 问题内容: 我有Clojure功能。 源代码: https://github.com/8protons/url62/blob/master/src/url62/core.clj 我需要从Java执行此功能。 我尝试使用这样的代码: 但这不起作用: 问题答案: 您忘记了Clojure命名空间: 这是项目结构: 和文件: 这是调用嵌入式Clojure函数的Java类: Clojure文件: Cloju