Как я могу перенаправить стандартный вывод IronPython в C#?
У меня есть следующее:
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 ответа
Вы можете установить поток и текстовый редактор непосредственно из 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;
}
Ваш пример близок к работе.
Проблема, которую вы видели, заключается в том, что 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;
}
}
Это работало нормально для меня
pyRuntime = Python.CreateRuntime();
pyRuntime.IO.SetOutput(Console.OpenStandardOutput(), new UTF8Encoding(true, false));