Как я могу перенаправить стандартный вывод IronPython в C #? - PullRequest
15 голосов
/ 16 июня 2010

У меня есть следующее:

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

    private void button3_Click(object sender, EventArgs e)
    {
        try
        {
            var strExpression = @"
            import sys
            sys.stdout=my.write
            print 'ABC'
            ";
            var engine = Python.CreateEngine();
            var scope = engine.CreateScope();
            var sourceCode = engine.CreateScriptSourceFromString(strExpression);
            scope.SetVariable("my", this);
            var actual = sourceCode.Execute<string>(scope);
            textBox1.Text += actual;
        }
        catch (System.Exception ex)
        {
            MessageBox.Show(ex.ToString());
        }
    }

    public void write(string s)
    {
        textBox1.Text += s;
    }
}

Но я получаю Exception, который говорит, что нет write.

Что я делаю неправильно?

Ответы [ 3 ]

25 голосов
/ 16 июня 2010

Вы можете установить поток и текстовый редактор непосредственно из c #:

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

Например, чтобы перенаправить вывод, вы можете переопределить класс TextWriter новым, записав его в текстовое поле.


, например

В моем приложении я переопределил класс StreamWriter, который вызывает события, когда что-то записывается в поток (здесь только часть кода):

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
}

Тогда в вашем приложении вы должны сделать что-то вроде:

    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;
    }
3 голосов
/ 14 ноября 2012

Ваш пример близок к работе.

Проблема, которую вы видели, заключается в том, что sys.stdout=my.write должно быть sys.stdout=my.Также кажется, что Python ожидает найти логический атрибут softspace.

Я внес эти два изменения в приведенный ниже код.Надеюсь, теперь это должно работать так, как вы ожидали.

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 голосов
/ 03 ноября 2017

Это работало нормально для меня

        pyRuntime = Python.CreateRuntime();
        pyRuntime.IO.SetOutput(Console.OpenStandardOutput(), new UTF8Encoding(true, false));
...