How can I redirect the stdout of IronPython in C#?

后端 未结 3 1704
情话喂你
情话喂你 2020-12-05 11:04

I have the following:

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    private void button3_Click(objec         


        
相关标签:
3条回答
  • 2020-12-05 12:00

    You can set a stream and a textwriter directly from c#:

    engine.Runtime.IO.SetOutput(stream, txtWriter);
    engine.Runtime.IO.SetErrorOutput(stream, txtWriter);
    

    To redirect the output for example you could override TextWriter class with a new one writing on your textbox.


    e.g.

    in my application I did an override of StreamWriter class that rises events when something is written on the stream (here just a part of the code):

    public class MyEvtArgs<T> : EventArgs
    {
        public T Value
        {
            get;
            private set;
        }
        public MyEvtArgs(T value)
        {
            this.Value = value;
        }
    }
    
    
    public class EventRaisingStreamWriter : StreamWriter
    {
        #region Event
        public event EventHandler<MyEvtArgs<string>> StringWritten;
        #endregion
    
        #region CTOR
        public EventRaisingStreamWriter(Stream s):base(s)
        { }
        #endregion
    
        #region Private Methods
        private void LaunchEvent(string txtWritten)
        {
            if (StringWritten != null)
            {
                StringWritten(this, new MyEvtArgs<string>(txtWritten));
            }
        }
        #endregion
    
    
        #region Overrides
    
        public override void Write(string value)
        {
            base.Write(value);
            LaunchEvent(value);
        }
        public override void Write(bool value)
        {
            base.Write(value);
            LaunchEvent(value.ToString());
        }
        // here override all writing methods...
    
        #endregion
    }
    

    Then in your application you should just do something like:

        MemoryStream ms = new MemoryStream();
    
        EventRaisingStreamWriter outputWr = new EventRaisingStreamWriter(ms);
        outputWr.StringWritten += new EventHandler<MyEvtArgs<string>>(sWr_StringWritten);
    
        var engine = Python.CreateEngine();
        engine.Runtime.IO.SetOutput(ms, outputWr);
        engine.CreateScriptSourceFromString("print 'hello world!'").Execute();
    
    
        void sWr_StringWritten(object sender, MyEvtArgs<string> e)
        {
            textBox1.Text += e.Value;
        }
    
    0 讨论(0)
  • 2020-12-05 12:03

    Your example is close to working.

    The problem you saw is because sys.stdout=my.write should be sys.stdout=my. It also appears that Python expects to find a boolean softspace attribute.

    I have made these two changes in the code below. Hopefully this should now work as you expected.

    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
    
        private void button3_Click(object sender, EventArgs e)
        {
            try
            {
                var strExpression = @"
    import sys
    sys.stdout=my
    print 'ABC' ";
    
                var engine = Python.CreateEngine();
                var scope = engine.CreateScope();
                var sourceCode = engine.CreateScriptSourceFromString(strExpression);
                scope.SetVariable("my", this);
                var actual = sourceCode.Execute(scope);
                textBox1.Text += actual;
            } catch (System.Exception ex) {
                MessageBox.Show(ex.ToString());
            }
        }
    
        public bool softspace;
    
        public void write(string s)
        {
            textBox1.Text += s;
        }
    }
    
    0 讨论(0)
  • 2020-12-05 12:06

    This worked fine for me

            pyRuntime = Python.CreateRuntime();
            pyRuntime.IO.SetOutput(Console.OpenStandardOutput(), new UTF8Encoding(true, false));
    
    0 讨论(0)
提交回复
热议问题