简体   繁体   中英

DataReceivedEvent not hit while Interacting with (Python) process from redirected input/output/error

I am trying to control a python session from C# using standard input & output.

After starting Python process, I expect to continue sending commands to it and receive the output to my WinForms Textbox.

After trying many SO answers and MSDN, any suggestions on why the DataReceivedEvent Handler is not invoked ? Full Code follows:

Note that to generate Newline from Python, I enter this in the Command Text import os;print os.linesep

using System;
using System.Diagnostics;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        private static Process InterProc;
        public Form1()
        {
            InitializeComponent();
            InterProc = new Process();
            InitializeInterpreter();
        }

        private void InitializeInterpreter()
        {
            InterProc.StartInfo.UseShellExecute = false;
            InterProc.StartInfo.FileName = @"C:\Python27\python.exe";
            InterProc.StartInfo.RedirectStandardInput = true;
            InterProc.StartInfo.RedirectStandardOutput = true;
            InterProc.StartInfo.RedirectStandardError = true;
            InterProc.StartInfo.CreateNoWindow = true;
            InterProc.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
            InterProc.OutputDataReceived += new DataReceivedEventHandler(InterProcOutputHandler);

            bool started = InterProc.Start();

            InterProc.BeginOutputReadLine();
        }

        private void AppendTextInBox(TextBox box, string text)
        {
            if (this.InvokeRequired)
            {
                this.Invoke((Action<TextBox, string>)AppendTextInBox, OutputTextBox, text);
            }
            else
            {
                box.Text += text;
            }
        }

        private void InterProcOutputHandler(object sendingProcess, DataReceivedEventArgs outLine)
        {
            AppendTextInBox(OutputTextBox, outLine.Data + Environment.NewLine);
        }

        private void Enterbutton_Click(object sender, EventArgs e)
        {
            InterProc.StandardInput.WriteLine(CommandTextBox.Text);
        }
    }
}

This might help others for whom the solution above did not work. I have been having exactly the same problem and been struggling with it and eventually found this question and answer.

For me, the StdError via ErrorDataReceived was being triggered for Error output and it was just the Stdout via OutputDataReceived which was not triggered.

I was running dotnet core on Linux (Raspberry Pi), but I also had the same problem running this on Windows.

My code was basically the same as the answer from vijiboy, so I added the -i option to Python, but it made no difference! But it inspired me to look closer at the Python options where I found this:

-u : force the stdout and stderr streams to be unbuffered; this option has no effect on stdin; also PYTHONUNBUFFERED=x

so adding -u when calling Python (removing -i) solved the issue, and finally OutputDataReceived was triggered!

This answer is for people who land up here wanting yet another among many answers out there on SO.

The code which finally got interacting with python session is given below:
Note 1: Invoke Python with '-i' argument. (refer Process Arguments -i below)
Note 2: Trying synchronous read from std error freezed ( Process.StandardError.ReadToEnd() ). So both the std output and error streams needed to be provided with a handler call back (refer InterProcOutputHandler below)

using System;
using System.Diagnostics;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        private static Process InterProc;
        public Form1()
        {
            InitializeComponent();
            InterProc = new Process();
            InitializeInterpreter();
        }

        private void InitializeInterpreter()
        {
            InterProc.StartInfo.FileName = @"C:\Python27\python.exe";
            InterProc.StartInfo.Arguments = @"-i"; // drops python into interactive mode after executing script if passed any
            InterProc.StartInfo.UseShellExecute = false;
            InterProc.StartInfo.RedirectStandardInput = true;
            InterProc.StartInfo.RedirectStandardOutput = true;
            InterProc.StartInfo.RedirectStandardError = true;
            InterProc.StartInfo.CreateNoWindow = true;
            InterProc.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
            InterProc.OutputDataReceived += new DataReceivedEventHandler(InterProcOutputHandler);
            InterProc.ErrorDataReceived += new DataReceivedEventHandler(InterProcOutputHandler);

            bool started = InterProc.Start();

            InterProc.BeginOutputReadLine();
            InterProc.BeginErrorReadLine();
        }

        private void AppendTextInBox(TextBox box, string text)
        {
            if (InvokeRequired)
            {
                Invoke((Action<TextBox, string>)AppendTextInBox, OutputTextBox, text);
            }
            else
            {
                box.Text += text;
            }
        }

        private void InterProcOutputHandler(object sendingProcess, DataReceivedEventArgs outLine)
        {
            AppendTextInBox(OutputTextBox, outLine.Data + Environment.NewLine);
        }

        private void Enterbutton_Click(object sender, EventArgs e)
        {
            InterProc.StandardInput.WriteLine(CommandTextBox.Text);
        }
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM