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-14 19:30:48
|
Hi, Thanks for using Py4J! short answer to your question: creating a Java shim is the way to go for now, but I'm willing to at least allow the option to prevent autoboxing so that if you create a java.lang.Byte, it is not converted to an int and it stays an instance of JavaObject on the Python side. I'll look at the code tonight and get back to you if that's something I can implement relatively quickly. alternative: you can pass a byte array and then use something like ArrayUtils from Apache Commons to create your list: gateway.jvm.org.apache.commons.lang.ArrayUtils.toObject(bytes([1, 2, 3])) long answer: matching primitives is difficult because of the inherent differences in the Java and Python type systems. Py4J. Py4J tries to optimize for the common case and expect the user to create Java shims when the default type conversion does not match the desired use case for primitives. HTH, 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 > |