通过 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调用java代码-jpype

Python安装jpype调用java,安装jaydebeapi通过jdbc连接数据库

python调用java程序--jpype

如何用Jpype创建HashMap和ArrayList

jpype测试报错,找不到类raise _RUNTIMEEXCEPTION.PYEXC("Class %s not found" % name)

Jpype:在jar中导入类时出现ModuleNotFoundError