py4j icon indicating copy to clipboard operation
py4j copied to clipboard

Catch Java Exceptions in Python

Open bartdag opened this issue 10 years ago • 2 comments

I see two use cases. The first is the easiest to implement:

# Use case 1
try:
    gw.entry_point.doSomething()
except gw.jvm.java.io.IOError.as_type():
    print("Hello World")

# Alternative
try:
    gw.entry_point.doSomething()
except gw.jvm.java.io.IOError:
    print("Hello World")

The second one is trickier and will require metaprogramming (IOError must be a type...)

In all cases, we will need a type registry on the python side so that we do no create more than one type per java class. The type registry should probably be tied to the gateway and thread safe (oh my!). A global registry might make sense though.

Finally, we will need some sort of support for hierarchy (IOError is a child of java.lang.Error). This could be expensive.

bartdag avatar Dec 30 '14 21:12 bartdag

Some food for thought/design notes:

In [1]: class JavaClass(type):
   ...:     def hello(cls):
   ...:         print("Hello world")
   ...:

In [2]: JavaString = JavaClass("JavaString", (object,), {})

In [3]: js = JavaString()

In [4]: isinstance(js, JavaString)
Out[4]: True

In [5]: isinstance(JavaString, JavaClass)
Out[5]: True

In [6]: JavaString.hello()
Hello world

Notes:

  1. It might be possible to make JavaClass a type (metaclass).
  2. We may be able to make gateway.jvm.java.util.ArrayList a type with metaclass JavaClass.
  3. The parent of ArrayList would be List and so on. In the end though, it would be JavaObject. So we would have:
    1. isinstance(ArrayList, py4j.java_gateway.JavaClass)
    2. isinstance(ArrayList(), py4j.java_gateway.JavaObject)
    3. isinstance(ArrayList(), gateway.jvm.java.util.ArrayList)
    4. isinstance(ArrayList(), gateway.jvm.java.util.Collection)
  4. I read that metaclasses may have some performance cost.
  5. Re-creating the entire class hierarchy (with interfaces) might be very costly.
  6. Difficult to do it lazily (we would have to change bases if we go the lazy/dynamic route)
  7. It may break backward compatibility, but I'm not sure how (the tests above show that we can keep most of the actual behavior).
  8. Still not sure how that would work with py4j.java_collections.
  9. Still not sure if I like this design. I really liked that Py4J was just a wrapper/proxy and was not trying to bring the whole Java type system to Python.

bartdag avatar Dec 31 '14 02:12 bartdag

# Use case 1
try:
    gw.entry_point.doSomething()
except gw.jvm.java.io.IOError.as_type():
    print("Hello World")

# Alternative
try:
    gw.entry_point.doSomething()
except gw.jvm.java.io.IOError:
    print("Hello World")

This would be super cool - any plans to add this in? thank you

Tagar avatar Oct 15 '20 05:10 Tagar