Search code examples
c#pythonunity-game-engineprocessipc

.NET Intercepted STDOUT from Python is always empty in Unity


I'm trying to use a Python program to send a continuous stream of information from one program to another, like this question, but in byte form.

pythonPath and pythonScript are just the file locations of the script and python.exe.

C# code

public static void PythonKernel_Test() {
    Process pythonProcess = Process.Start(new ProcessStartInfo() {
        FileName = pythonPath,
        Arguments = pythonScript,
        RedirectStandardOutput = true,
        RedirectStandardInput = true,
        UseShellExecute = false,
        CreateNoWindow = true
    });
    Stream pythonStdOut = pythonProcess.StandardOutput.BaseStream;
    for (int i = 0; i < 1000; i++) {
        byte[] buffer = new byte[256];
        pythonStdOut.Read(buffer, 0, 256);
        Debug.Log(Encoding.ASCII.GetString(buffer) + Environment.NewLine + BitConverter.ToString(buffer));
    }
    pythonStdOut.Close();
}

Although this is in Unity, you could just substitute Debug.Log for Console.WriteLine().

However, even though I am spamming stdout with SYNC, nothing appears on the C# side. It does however, appear in the command prompt when ran from shell.

Python code

w = sys.stdout.buffer
while True:
    w.write(b"SYNC\n")
    sys.stdout.flush()

Solution

  • Here a working sample to try out

    public static void PythonKernel_Test()
    {
        var pi = new ProcessStartInfo
        {
            FileName = "python",
            Arguments = "test.py",
            RedirectStandardOutput = true,
            RedirectStandardError = true,
            CreateNoWindow = true,
        };
        var pythonProcess = new Process
        {
            StartInfo = pi,
        };
    
        pythonProcess.OutputDataReceived+= (s,e) => 
        {
            Console.WriteLine("OUT: {0}",e.Data);
        };
        pythonProcess.ErrorDataReceived+= (s,e) => 
        {
            Console.WriteLine("ERR: {0}",e.Data);
        };
    
        pythonProcess.Start();
        pythonProcess.BeginOutputReadLine();
        pythonProcess.BeginErrorReadLine();
        pythonProcess.WaitForExit();
    }
    

    It will read the output asynchronously

    Taken from https://stackoverflow.com/a/29753402/1744164

    test.py

    import sys
    
    while True:
        sys.stdout.write(b"SYNC\n")
        sys.stdout.flush()