I have a script that can run a python string but if there is an error I want to be able to get a string formatted like a standard python error. I'm using IronPython 3.4
This is the C# code I currently have:
using UnityEngine;
using IronPython.Hosting;
using System.IO;
public class test : MonoBehaviour
{
void Start()
{
var memoryStream = new MemoryStream();
var engine = Python.CreateEngine();
engine.Runtime.IO.SetOutput(memoryStream, System.Text.Encoding.Default);
var scope = engine.CreateScope();
string code = @"print(var)";
try {
var source = engine.CreateScriptSourceFromString(code);
source.Execute(scope);
}
catch(System.Exception e)
{
Debug.Log(e);
}
Debug.Log(System.Text.Encoding.ASCII.GetString(memoryStream.ToArray()));
}
}
What I want to be output is something like this:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'var' is not defined
I tried using engine.Runtime.IO.SetErrorOutput
but that didn't do anything.
After more digging I found pythonContext.FormatException(e)
which gave me exactly what I needed. To get the Python context I used PythonContext context = (PythonContext)Microsoft.Scripting.Hosting.Providers.HostingHelpers.GetLanguageContext(engine);
So in the end I got this code:
using UnityEngine;
using IronPython.Hosting;
using IronPython.Runtime;
using System.IO;
public class test : MonoBehaviour
{
void Start()
{
var memoryStream = new MemoryStream();
var engine = Python.CreateEngine();
PythonContext context = (PythonContext)Microsoft.Scripting.Hosting.Providers.HostingHelpers.GetLanguageContext(engine);
engine.Runtime.IO.SetErrorOutput(memoryStream, System.Text.Encoding.Default);
var scope = engine.CreateScope();
string code = @"print(var)";
try {
var source = engine.CreateScriptSourceFromString(code);
source.Execute(scope);
}
catch(System.Exception e)
{
Debug.Log(context.FormatException(e));
}
Debug.Log(System.Text.Encoding.ASCII.GetString(memoryStream.ToArray()));
}
}