如何从python/numpy调用java函数? P>我清楚地知道如何用C++来扩展Python,但是如果我想用java编写一个函数来使用NUMPY呢?p>
下面是一个简单的场景:我想使用Java类计算numpy数组的平均值。如何将numpy向量传递给Java类并收集结果如何从python/numpy调用java函数? P>我清楚地知道如何用C++来扩展Python,但是如果我想用java编写一个函数来使用NUMPY呢?p>,java,numpy,Java,Numpy,下面是一个简单的场景:我想使用Java类计算numpy数组的平均值。如何将numpy向量传递给Java类并收集结果 谢谢你的帮助 我不确定numpy是否支持,但以下内容可能会有所帮助: 我花了一些时间回答我自己的问题,并想与大家分享我的答案,因为我觉得关于stackoverflow这个主题的信息不多。我还认为,由于Java性能的提高和其他良好的软件开发特性,Java将在科学计算中变得更加重要(例如,请参阅数据挖掘的WEKA软件包) 一般来说,使用正确的工具,用Java扩展Python要比用C/
谢谢你的帮助 我不确定numpy是否支持,但以下内容可能会有所帮助:
我花了一些时间回答我自己的问题,并想与大家分享我的答案,因为我觉得关于stackoverflow这个主题的信息不多。我还认为,由于Java性能的提高和其他良好的软件开发特性,Java将在科学计算中变得更加重要(例如,请参阅数据挖掘的WEKA软件包)
一般来说,使用正确的工具,用Java扩展Python要比用C/C++容易得多
概述和评估从Python调用Java的工具
- :因为没有适当的理由 这个工具是无用的
- Py4J:需要在使用python之前启动Java进程。作为 其他人认为这是一个可能的失败点。此外,没有多少使用实例被记录在案
- 当前位置虽然发展似乎是死亡,但它运行良好,并且存在 web上的许多示例(例如,有关使用Java编写的数据挖掘库的信息,请参阅)。因此我决定集中精力 在这个工具上
self.javaHome = '/usr/java/default'
然后运行:
sudo python setup.py install
成功安装后,请检查此文件:
/usr/lib64/python2.7/site-packages/jpype//u 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
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数组的函数。因为没有状态的概念,所以我使用静态函数,所以我不需要创建任何Java对象(创建Java对象不会改变任何东西)
我认为Jython是最好的选项之一,这使得它在Python中使用java对象变得无缝。实际上,我将weka与python程序集成在一起,非常简单。只需导入weka类并在python代码中调用它们,就像在java中那样
看看,我不是真的在寻找克隆,因为我有很多numpy代码,我觉得numpy非常好。这是一个很小的问题,没有直接的方法将numpy与Java结合使用……Java代码库的大小是否足够大,以至于您无法在Cython中重新编写对性能敏感的部分,并在其余部分使用numpy/python?这更是一个战略决策,我现在没有很多Java代码。很多人使用C++进行科学计算,但我觉得java将来可能取代C++。因此理想的Python/NoMyb应该能够同时使用C++和java类(如Matlab)。如果垃圾收集确实是个问题,那么就可以用C++来扩展Python,否则java将更好地看到在科学界广泛使用java的任何趋势,而且,听起来好像没有很多代码要转换,它最好使用Cython这样的工具。而不是用Java踏入未知和不受支持的水域。战略决策更可能是使用当今可用技术的务实决策。这可能会有所帮助,但我希望在一些使用更高级包装器的逐步说明中有所帮助。理论上,1)应该调用C++的java,然后2)从Python调用C++。此外,JCC的文档很可怕(或者我应该说不存在),我没有得到任何线索来说明如何使用它……是的,我知道。但是jython的问题是,不幸的是,它不支持numpy以及许多其他用于科学计算的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()
/**
* 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);
}
}
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()