ironpython3
ironpython3 copied to clipboard
Derived exceptions not caught by C#
For example:
class Test(SystemExit): pass
raise Test
does not terminate the process. The C# code expects a SystemExitException
but the exception ends up being of type Exception
.
Also, an IndexError
(which becomes an IndexOutOfRangeException
) would not be caught by LookupException
handler in C# even though LookupError
is a base of IndexError
. For example:
try {
PythonCalls.Call(context, somethingthatthrowsindexerror);
} catch (LookupException e) {
// do stuff
}
would not catch the exception.
This came up in https://github.com/IronLanguages/ironpython3/pull/1011.
Probably related: raising a subclass of SystemExit displays a stack trace rather than exiting silently.
Found this in docopt module. It raises DocoptExit which is a subclasss of SystemExit.
Apparently, by design, any user-defined exception is a subclass of System.Exception
, as per documentation. My guess is that this is to allow multiple inheritance.
A working way of catching Python exceptions in C# including their subclasses is with a when
clause:
try {
PythonCalls.Call(context, somethingthatthrowsindexerror);
} catch (Exception ex) when (PythonOps.IsInstance(ex.GetPythonException(), PythonExceptions.LookupError)) {
// do stuff
}
Note: the methods used are currently internal. An idea: define a public helper method checking exception subclasses.
Apparently, by design, any user-defined exception is a subclass of
System.Exception
, as per documentation. My guess is that this is to allow multiple inheritance.
Hmm, still seems like it would be cleaner to have it be a subclass of the more specific .NET class (e.g. SystemExitException
).
Note: the methods used are currently internal. An idea: define a public helper method checking exception subclasses.
As you know my preference is to have everything be internal unless there's a specific reason (or request) for it to be public. A helper method could be interesting (and possibly more efficient than an IsInstance call).
Anyway, at the very least we should special case SystemExit
since we know it's an issue...
I guess multiple inheritance on user types makes it complicated to have something other than System.Exception
as the .NET exception type:
class MyError(ValueError, AttributeError): pass