Re: [Py4j-users] How can I pass a List<short> or List<byte> from Python to Java?
Status: Beta
Brought to you by:
barthe
From: Barthelemy D. <bar...@in...> - 2015-07-15 00:25:00
|
After some investigation, there is no easy or quick solution because of the difference in the type systems and the autoboxing behavior of Java. From a design perspective, I'm pretty sure converting primitives such as short to Python int is saner than trying to track the original primitive type. Preventing primitive wrapper (such as Byte and Short) from being converted to Python int though makes a lot of sense, but requires a few non trivial changes. It's doable and I have a plan, but it won't be available before a few weeks, so your best bet on the short term is to rely on a Java shim or a third party library. Link to Github issue for reference: https://github.com/bartdag/py4j/issues/163 Barthelemy On Tue, Jul 14, 2015 at 2:26 PM Dan O'Reilly <ore...@gm...> wrote: > 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 > > > ------------------------------------------------------------------------------ > Don't Limit Your Business. Reach for the Cloud. > GigeNET's Cloud Solutions provide you with the tools and support that > you need to offload your IT needs and focus on growing your business. > Configured For All Businesses. Start Your Cloud Today. > https://www.gigenetcloud.com/ > _______________________________________________ > Py4j-users mailing list > Py4...@li... > https://lists.sourceforge.net/lists/listinfo/py4j-users > |