Thanks for responding @Palash01
I was hoping to avoid parsing the text of the exceptions looking for errors, but it does seem like that's the way to go. The exception passed doesn't have the java_exception attribute because it's not a Py4JJavaError but rather a generic Exception with the text of the Py4JJavaError. Here's the source code in dbutils we're dealing with:
def prettify_exception_message(f):
"""
This is a decorator function that aims to properly display errors that happened on the
Scala side. Without such handling, stack traces from Scala are displayed at the
bottom of error output, and are easily missed. We fix this by catching Py4JJavaError
and throwing another exception with the error message from Scala side.
"""
def f_with_exception_handling(*args, **kwargs):
try:
return f(*args, **kwargs)
except Py4JJavaError as e:
class ExecutionError(Exception):
pass
# In Python 3, we need to use the new 'raise X from None' syntax
# to suppress the original exception's traceback. However, we
# can't directly use that syntax because we need to be compatible
# with Python 2. It might appear that six's `raise_from` would
# handle this but that function's implementation is wrong and the
# six won't fix it: https://github.com/benjaminp/six/issues/193.
# Therefore, we need this gross hack derived from PEP-409:
exc = ExecutionError(str(e))
exc.__context__ = None
exc.__cause__ = None
raise exc
return f_with_exception_handling
So as you said, we can catch all exceptions and try to determine the type of exception from the text of the error and stack trace, but it will have to be on str(e) instead of str(e.java_exception):
try:
dbutils.fs.ls(test_location)
except Exception as e:
if "java.io.FileNotFoundException" in str(e):
print("Caught a java.io.FileNotFoundException")
else:
# Handle other exceptions or re-raise them if needed
raise
I do wish we could just handle the Py4JJavaError and leave other exceptions unhandled instead of having to reraise, but I guess it's not really a big deal.
For anyone that is willing to try, though I don't recommend it, I think you could in theory create a custom class that inherits from DBUtils and modifies this method such that you could catch this specific exception. More specifically, I'm thinking you could define the exception class under FSHandler instead of having the class be function scoped. I am wondering why it isn't this way in the source code.