c# - 将 stdout/stderr 从 .NET 应用程序中嵌入的 Python 重定向到文本框

标签 c# python .net winforms python.net

我正在尝试使用 Python.NET 在 C# Windows 窗体应用程序中嵌入交互式 Python shell .

我能够将解释器嵌入我的 C# 应用程序并从 .NET 访问 Python 模块。我现在正尝试将输出和错误从 Python 解释器重定向到 .NET 文本框。虽然我能够将标准输出重定向到一个文件,但我在将输出路由到文本框时遇到了问题。

这是我目前尝试过的: 这个想法是将 Python 的 sys.stdout 分配给一个 .NET 对象,该对象实现与 python 流相同的接口(interface)(write()、writelines()...):

.NET 类模仿 Python 流:

public class TextBoxStream : PyObject // To assign to sys.stdout. Is this correct?
{
    private TextBox _output = null;            

    public TextBoxStream() {}

    public TextBoxStream(TextBox output)
    {
        _output = output;
    }

    void write(object value)
    {
        _output.AppendText(value.ToString());
    }

    void writelines(object value)
    {
    }
}

在 Form1.cs 中:

private void button1_Click(object sender, EventArgs e)
{
    using (Py.GIL())
    {
        // Redirect stdout to text box
        dynamic sys = PythonEngine.ImportModule("sys");
        TextBoxStream textBoxStream = new TextBoxStream(textBox1);
        sys.stdout = textBoxStream;
        //sys.SetAttr("stdout", textBoxStream); // This did not work either
        string code =
            "import sys\n" +
            "print 'Message 1'\n" +
            "sys.stdout.write('Message 2')\n" +
            "sys.stdout.flush()";

        PyObject redirectPyObj = PythonEngine.RunString(code); // NULL
        sys.stdout.write("Message 3"); 
        // Exception thrown: 'Python.Runtime.PyObject' does not contain a definition for 'stdout'
    }
}

这也不起作用:redirectPyObj 为 NULL。我尝试使用旧的和新的 Python.NET API(动态)。 sys.stdout.write 和 print 语句都不会写入文本框。

关于如何解决这个问题的任何想法都会非常有帮助。

最佳答案

对我有用的解决方案是将 Python stdout/stderr 重定向到 Python 中的流。然后,我能够将此流路由到 .NET 文本框中。

private void button1_Click(object sender, EventArgs e)
{
    using (Py.GIL())
    {
        // Redirect stdout to text box
        dynamic sys = PythonEngine.ImportModule("sys");

        string codeToRedirectOutput =
            "import sys\n" +
            "from io import StringIO\n" +
            "sys.stdout = mystdout = StringIO()\n" +
            "sys.stdout.flush()\n" +
            "sys.stderr = mystderr = StringIO()\n" +
            "sys.stderr.flush()\n";
        PythonEngine.RunString(codeToRedirectOutput);            

        // Run Python code
        string pyCode = "print(1 + 2)";
        PyObject result = PythonEngine.RunString(pyCode); // null in case of error
        if (result != null)
        {
            string pyStdout = sys.stdout.getvalue(); // Get stdout
            pyStdout = pyStdout.Replace("\n", "\r\n"); // To support newline for textbox
            textBox1.Text = pyStdout;             
        }
        else
        {
             PythonEngine.PrintError(); // Make Python engine print errors
             string pyStderr = sys.stderr.getvalue(); // Get stderr
             pyStderr = pyStderr.Replace("\n", "\r\n"); // To support newline for textbox
             textBox1.Text = pyStderr;
        }     
    }
}

使用这段代码,我能够将 Python 引擎的 stdout(和错误情况下的 stderr)重定向到 .NET 文本框。

关于c# - 将 stdout/stderr 从 .NET 应用程序中嵌入的 Python 重定向到文本框,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37289082/

相关文章:

python - ZIP 格式重复字符

python - 时间序列的分割 Pandas 数据框

.net - 在 .NET 中使用 DataColumn.Expression 属性的嵌套 IF 语句

c# - 用数字保证精度?

c# - log4net 在每一行打印日期时间/调用类/函数

python - 突然在运行测试时我得到 "TypeError: ' NoneType' object is not iterable

c# - 不同用户时远程注册表始终为空

c# - 如何使用 Mono.ZeroConf 注册服务?

c# - ThrowingException 导致 UnitTest 中断?

c# - .net c# 中的 Web api 路由属性正则表达式中的字符串参数应仅允许字母数字和点