[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 |