2016-05-18 8 views
2

Python.NETを使用して、C#Windows Formsアプリケーションに対話的なPythonシェルを埋め込もうとしています。.NETアプリケーションに埋め込まれたPythonからstdout/stderrをテキストボックスにリダイレクト

私はC#アプリケーションにインタプリタを埋め込み、.NETのPythonモジュールにアクセスできました。私は現在、出力とエラーをPythonインタプリタから.NETテキストボックスにリダイレクトしようとしています。標準出力をファイルにリダイレクトできますが、出力をテキストボックスにルーティングする際に問題があります。 アイデアは、Pythonのストリーム(write()、writelines()...)と同じインタフェースを実装する.NETオブジェクトにPythonのsys.stdoutを割り当てることでした。 Pythonの流れを模倣する

.NETクラス:Form1.csで

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) 
    { 
    } 
} 

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ステートメントのどちらもテキストボックスに書き込まれません。

これにアプローチする方法については、非常に参考になります。

+1

この方法を試しましたか? http://stackoverflow.com/a/4307737/2230844本質的に、python stdoutをpython変数にリダイレクトし、.NETからこの変数をクエリします。 – denfromufa

+0

私は同様のアプローチで標準出力リダイレクションを得ることができましたが、stderrリダイレクションに問題がありました。あなたのリンクされた答えは、私がPyErr_Print()を使ってPythonEngineにエラーを書き出させなければならないことに気付きました。ありがとう! – Spry

+2

@denfromufa、私はあなたが質問を閉じるために答えを投稿したことに気をつけていないと思います。それは、他の誰かがC#ソリューションを探しているのを助けるかもしれません。 – Spry

答えて

2

私のために働いた解決策は、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; 
     }  
    } 
} 

、Iは、.NETのテキストボックスにPythonのエンジンから(エラーの場合およびstderr)標準出力をリダイレクトすることができました。

関連する問題