6

I'm trying to run a python script from C# and I want to get the output line by line and not at the end. I feel like I'm missing something important, but don't know what. This is what I have so far:

static void Main(string[] args)
{
    var cmd = "C:/Users/user/Documents/script.py";
    var process = new Process
    {
        StartInfo = new ProcessStartInfo
        {
            FileName = "C:/Users/user/AppData/Local/Programs/Python/Python36/python.exe",
            Arguments = cmd,
            UseShellExecute = false,
            RedirectStandardOutput = true,
            RedirectStandardError = true,
            CreateNoWindow = true
        },
        EnableRaisingEvents = true
    };
    process.ErrorDataReceived += Process_OutputDataReceived;
    process.OutputDataReceived += Process_OutputDataReceived;

    process.Start();
    process.BeginErrorReadLine();
    process.BeginOutputReadLine();
    process.WaitForExit();
    Console.Read();
}

static void Process_OutputDataReceived(object sender, DataReceivedEventArgs e)
{
    Console.WriteLine(e.Data);
}

And the python code:

import time

for i in range(5):
    print("Hello World " + str(i))
    time.sleep(1)
Terry Anderson
  • 117
  • 1
  • 1
  • 8
  • 1
    Are we to assume that you are getting output, but you're getting it all at once? This is not stated in the question. –  Nov 19 '18 at 18:34
  • I am getting output, but at the end of the 5 seconds. – Terry Anderson Nov 19 '18 at 18:35
  • 1
    By default `print` does not flush the output. There are several ways of doing that, depending on your python version. See: https://stackoverflow.com/questions/230751/how-to-flush-output-of-print-function –  Nov 19 '18 at 18:37

1 Answers1

12

change your python code to the following:

import time
import sys
for i in range(5):
    print("Hello World " + str(i))
    sys.stdout.flush()
    time.sleep(1)

or just edit your c# code and use -u switch:

var cmd = "-u C:/Users/user/Documents/script.py";

When standard output it was being redirected, the event in C# wasn't being raised when a line was written on console because there were no calls to stdout.flush;

Putting a stdout.flush() statement after each print statement made the events fire as they should and C# now captures the output as it comes.

Or you could just use -u switch.

Ehsan.Saradar
  • 664
  • 6
  • 10
  • This works perfectly. Apparently I didn't know about the flushing mechanism. – Terry Anderson Nov 19 '18 at 18:42
  • 2
    Note that if you don't want to modify the python code, there are alternative ways of accomplishing this. See my link under your question. the command-line argument `-u` will use unbuffered streams. –  Nov 19 '18 at 18:57
  • -u works perfect – Vincent Oct 30 '21 at 08:00