我一直在使用py4j围绕用户不太友好的Java库构建一个用户友好的Python库。在大多数情况下,这是一件轻而易举的事,py4j一直是一个很棒的工具。但是,在Python和Java之间发送矩阵时,我遇到了麻烦。
具体来说,我在java中有一个静态函数,它接受一个整数矩阵作为参数:
public class MyClass {
// ...
public static MyObject create(int[][] matrix) {
// ...
}
}
我希望能够像这样从Py4j中调用它:
def create_java_object(numpy_matrix):
# <code here checks that numpy_matrix is a (3 x n) integer matrix>
# ...
return java_instance.jvm.my.namespace.MyClass.create(numpy_matrix)
这不起作用,这并不太令人惊讶,如果将numpy_matrix
转换为普通python列表列表,它也不起作用。我原以为解决方案是在函数调用之前构造一个java数组并传输数据:
def create_java_object(numpy_matrix):
# <code here checks that numpy_matrix is a (3 x n) integer matrix>
# ...
java_matrix = java_instance.new_array(java_instance.jvm.int, 3, n)
for i in range(numpy_matrix.shape[1]):
java_matrix[0][i] = int(numpy_matrix[0, i])
java_matrix[1][i] = int(numpy_matrix[1, i])
java_matrix[2][i] = int(numpy_matrix[2, i])
return java_instance.jvm.my.namespace.MyClass.create(java_matrix)
现在,此代码正确运行。但是,它需要大约两分钟才能运行。顺便说一句,我正在使用的矩阵大约为(3 x~300,000)元素。
在Py4j中是否有规范的方法来转换矩阵不需要花费大量时间?我不介意花一两秒钟,但这太慢了。如果没有为这种通信设置Py4j,那么Python的Java互操作库是否存在?
注意:Java库将int[][]
矩阵视为不可变数组;即,它从不试图修改它。
答案 0 :(得分:3)
我发现这个特殊情况的解决方案有效;虽然它不是非常优雅:
Py4j支持有效地将Python <configuration />
对象作为bytearray
数组传递给Java。我通过修改原始库和我的Python代码解决了这个问题。
新的Java代码:
byte[]
新的Python代码:
public class MyClass {
// ...
public static MyObject create(int[][] matrix) {
// ...
}
public static MyObject createFromPy4j(byte[] data) {
java.nio.ByteBuffer buf = java.nio.ByteBuffer.wrap(data);
int n = buf.getInt(), m = buf.getInt();
int[][] matrix = new int[n][m];
for (int i = 0; i < n; ++i)
for (int j = 0; j < m; ++j)
matrix[i][j] = buf.getInt();
return MyClass.create(matrix);
}
}
这会在几秒钟而不是几分钟内完成。