[Py4j-users] How can I pass a List<short> or List<byte> from Python to Java?
Status: Beta
Brought to you by:
barthe
|
From: Dan O'R. <ore...@gm...> - 2015-07-14 18:26:36
|
It seems that on the Python side, Py4J will automatically convert the java
type short (and byte) to the Python type int, which means there's no way to
pass a List<short> from Python to Java. Consider this example:
import java.util.List;
import py4j.GatewayServer;
class Test {
public void testByte(List<Byte> l) {
Byte i = l.get(0);
}
public static void main(String[] args) {
GatewayServer gw = new GatewayServer(new Test());
gw.start();
System.out.println("GatewayServer started...");
}
}
If I try to call testByte from the Python side, I seem to get an
ClassCastException no matter what I try:
>>> gw = JavaGateway()
>>> z = ListConverter().convert([1,2], gw._gateway_client)
>>> gw.entry_point.testByte(z)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/local/lib/python2.7/dist-packages/py4j/java_gateway.py", line
538, in __call__
self.target_id, self.name)
File "/usr/local/lib/python2.7/dist-packages/py4j/protocol.py", line 300,
in get_return_value
format(target_id, '.', name), value)
py4j.protocol.Py4JJavaError: An error occurred while calling t.testByte.
: java.lang.ClassCastException: java.lang.Integer cannot be cast to
java.lang.Byte
at Test.testByte(Test.java:8)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at py4j.reflection.MethodInvoker.invoke(MethodInvoker.java:231)
at py4j.reflection.ReflectionEngine.invoke(ReflectionEngine.java:379)
at py4j.Gateway.invoke(Gateway.java:259)
at py4j.commands.AbstractCommand.invokeMethod(AbstractCommand.java:133)
at py4j.commands.CallCommand.execute(CallCommand.java:79)
at py4j.GatewayConnection.run(GatewayConnection.java:207)
at java.lang.Thread.run(Thread.java:745)
>>> z =
ListConverter().convert([gw.jvm.java.lang.Byte(1),gw.jvm.java.lang.Byte(2)],
gw._gateway_client)
>>> gw.entry_point.testByte(z)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/local/lib/python2.7/dist-packages/py4j/java_gateway.py", line
538, in __call__
self.target_id, self.name)
File "/usr/local/lib/python2.7/dist-packages/py4j/protocol.py", line 300,
in get_return_value
format(target_id, '.', name), value)
py4j.protocol.Py4JJavaError: An error occurred while calling t.testByte.
: java.lang.ClassCastException: java.lang.Integer cannot be cast to
java.lang.Byte
at Test.testByte(Test.java:8)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at py4j.reflection.MethodInvoker.invoke(MethodInvoker.java:231)
at py4j.reflection.ReflectionEngine.invoke(ReflectionEngine.java:379)
at py4j.Gateway.invoke(Gateway.java:259)
at py4j.commands.AbstractCommand.invokeMethod(AbstractCommand.java:133)
at py4j.commands.CallCommand.execute(CallCommand.java:79)
at py4j.GatewayConnection.run(GatewayConnection.java:207)
at java.lang.Thread.run(Thread.java:745)
Is there some way to work around this? Ideally there would be away without
having to make changes on the Java-side, since for my actual use-case I'm
trying to call into an API I don't control. I could probably make things
work if I needed to call a Java shim instead, but I'd really like to avoid
that.
Thanks,
Dan O'Reilly
|