ironpython3 icon indicating copy to clipboard operation
ironpython3 copied to clipboard

Derived exceptions not caught by C#

Open slozier opened this issue 3 years ago • 4 comments

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.

slozier avatar Nov 02 '20 18:11 slozier

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.

orent avatar May 30 '22 13:05 orent

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.

BCSharp avatar May 30 '22 17:05 BCSharp

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...

slozier avatar May 30 '22 17:05 slozier

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

slozier avatar May 31 '22 00:05 slozier