Catching Ironpython Exception in C#

2020-06-17 06:56发布

I'm embedding IronPython 2.0 in C#. In IronPython, I defined my own exception with:

def foobarException(Exception):
    pass 

and raise it somewhere with:

raise foobarException( "This is the Exception Message" )

Now in C#, I have:

try
{
   callIronPython();
}
catch (Exception e)
{
   // How can I determine the name (foobarException) of the Exception
   // that is thrown from IronPython?   
   // With e.Message, I get "This is the Exception Message"
}

4条回答
我想做一个坏孩纸
2楼-- · 2020-06-17 07:14

When you catch an IronPython exception from C#, you can use the Python engine to format the traceback:

catch (Exception e)
{
    ExceptionOperations eo = _engine.GetService<ExceptionOperations>(); 
    string error = eo.FormatException(e); 
    Console.WriteLine(error);
}

You can pull the exception name out of the traceback. Otherwise, you will have to call into the IronPython hosting API to retrieve information directly from the exception instance. engine.Operations has useful methods for these kinds of interactions.

查看更多
▲ chillily
3楼-- · 2020-06-17 07:14

The way IronPython maps .NET exceptions to Python ones isn't always straightforward; a lot of exceptions are reported as SystemError (although if you import the .NET exception type you can specify that in the except clause). You can get the Python type of the exception using

type(e).__name__

If you want the .NET exception type, make sure you have import clr in the module. It makes .NET attributes available on objects, like the ToUpper() method on strings. Then you can access the .NET exception using the .clsException attribute:

import clr
try:
    1/0
except Exception, e:
    print type(e).__name__
    print type(e.clsException).__name__

prints:

ZeroDivisionError      # the python exception
DivideByZeroException  # the corresponding .NET exception

An example of catching the specific .NET exception you want:

from System import DivideByZeroException
try:
    1/0
except DivideByZeroException:
    print 'caught'
查看更多
家丑人穷心不美
4楼-- · 2020-06-17 07:20

My final solution was:

I have a result class in C# which is passed to my ironpython code. In Ironpython I fill the result class with all my computed values. To this class I just added a member variable IronPythonExceptionName. Now I just have a simple try in IronPython:

try: 
    complicatedIronPythonFunction()
except Exception, inst:
    result.IronPythonExceptionName = inst.__class__.__name__
    raise inst
查看更多
聊天终结者
5楼-- · 2020-06-17 07:23

Assuming that you compiled your python code with the .NET equivalent compiler you would have a static type which is just that exception. If this exception is public (exported type) then you reference the assembly that contains your python code in your project and dig up the type foobarException in some python namespace. That way C# will be able to type match that exception. This is the only way you can do that properly.

查看更多
登录 后发表回答