通过 JPype 和 numpy 将 Java 类型转换为 Python
Posted
技术标签:
【中文标题】通过 JPype 和 numpy 将 Java 类型转换为 Python【英文标题】:Java type conversion to Python through JPype and numpy 【发布时间】:2011-09-25 20:24:14 【问题描述】:我目前正在将一个用 Python 编写的程序移植到 Java,但遇到了一些问题。我当时正在移植程序的一部分,出于测试目的,我正在使用 JPype 使其与新的 java 类兼容。
编辑:为了让事情更清楚,我目前正在处理的类为 Python 程序的其余部分提供数据。
所以,在我的 java 类中,我在 ArrayLists 中有一些浮点值和字节值,
ArrayList<ArrayList<Float>> dataFloat = new ArrayList<ArrayList<Float>>();
ArrayList<ArrayList<Byte>> dataByte = new ArrayList<ArrayList<Byte>>();
然后通过使用 JPype,我可以将它们放入我现在具有类型的 Python 环境中
<class 'jpype._jclass.java.util.ArrayList'> .
现在我想简单地将这些转换为 Python 中的 numpy 数组,
numpy.array(dataFloat) .
一开始看起来很好用,打印出来的时候看起来不错,
[[1.0 2.0 3.0]
[80.0 127.0 127.0]
[255.0 255.0 255.0]] .
但是,它不适用于程序的其余部分,因为它要求值是浮点类型。进一步研究这个问题,我发现我拥有的这些“浮动”值实际上是
<class 'jpype._jclass.java.lang.Float'>
而不是我想要的常规 Python 浮点数。与常规的 numpy 浮点数组相比,
>>> b = array([[1.1, 2.1, 3.1], [4.1, 5.1, 6.1], [7.1, 8.1, 9.1]])
>>> type((b[0])[0])
<type 'numpy.float64'>
具有所需的浮点类型。
为了能够与 Python 程序的其余部分一起运行它,我必须使用 java Float.floatValue() 转换每个元素的数组,
arr = numpy.array(dataFloat)
a = array([])
for j in range(len(arr)):
b = array([])
if array_equal(a,[]):
for i in arr.get(j):
a = append(a, i.floatValue())
else:
for i in arr.get(j):
b = append(b, i.floatValue())
a = vstack((a, b))
这当然需要很多时间,尤其是当有数千个元素时。
有谁知道这可以有效地完成?简单地说,我从 JPype 中得到了很多 java.lang.Float 值,需要转换为常规的 Python 浮点值。
【问题讨论】:
你不能保持程序原样并在java代码中启动一个jython解释器吗? 对于初学者来说,我一点也不知道如何使用 jython,也不确定它提供了什么。从那时起我就认为 JPype 很好,我可以调用和使用我的 Java 类。这样,我不必对我的 Java 代码进行任何特殊修改即可进行测试,只需在 Python 代码中进行一些重写。到目前为止,我唯一遇到的问题就是这个。可以说我想继续使用 JPype 而不是乱用其他 JavaPython 包:) 基本上jython是在jvm上写的python。您可以在您的 java 中初始化一个 jython 解释器,然后将它提供给 python(基本上) 啊,好吧,我正在处理的类现在为 Python 程序的其余部分提供信息,而不是相反。那么在那种情况下,jython 不会有任何帮助吗? Jython 双向工作,但在这种情况下无济于事,因为 Numpy 部分是用 C 实现的,而 Jython 无法处理这些库。 【参考方案1】:我前段时间尝试过 JPype,但在类型转换方面也遇到了一些问题。也许您可以使用http://cython.org/ 加速您的代码,有一些方法可以加快对numpy 数据结构的访问:http://docs.cython.org/src/tutorial/numpy.html
进一步评论:vstack 和 hstack 可以使用任意列表/元组进行复制。所以你可以重写你的代码(未经测试)
arr = numpy.array(dataFloat)
a = []
for j in range(len(arr)):
b = array([])
for i in arr.get(j):
b = append(b, i.floatValue())
a.append(b)
a = vstack(a)
如果您避免调用 append(),您还可以进一步优化速度。使用固定大小 N 分配数组 b 会更快,例如使用 zero(),然后填充值:
arr = numpy.array(dataFloat)
N = ....
a = []
for j in range(len(arr)):
b = zeros((N,))
for k in range(N):
i =arr.get(j)[k]:
b[k] = i.floatValue()
a.append(b)
a = vstack(a)
这只有在你知道 N 时才有效。
【讨论】:
以上是关于通过 JPype 和 numpy 将 Java 类型转换为 Python的主要内容,如果未能解决你的问题,请参考以下文章
Python安装jpype调用java,安装jaydebeapi通过jdbc连接数据库
jpype测试报错,找不到类raise _RUNTIMEEXCEPTION.PYEXC("Class %s not found" % name)