How to repeatedly pass inputs and outputs between a C# Stream and a Python Script?

2.4k views Asked by At

I'm trying to run a Python script from C# as a stream, and to repeatedly pass inputs and outputs between Python and the stream, using StreamWriter and StreamReader.

I can read and write, but apparently only once, and not multiple times. (Which is what I need.) Hopefully, somebody can tell me what I'm doing wrong.

(I'm aware that I can probably do what I need to do by reading and writing to a file. However, I'd like to avoid this if I can, since using the Stream seems cleaner.)

Here's my C# code:

using System;
using System.Diagnostics;
using System.IO;

public class Stream_Read_Write
{
    public static void Main()
    {
        string path = "C:\\Users\\thomas\\Documents\\Python_Scripts\\io_test.py";
        string iter = "3";
        string input = "Hello!";

        stream_read_write(path, iter, input);

        //Keep Console Open for Debug
        Console.Write("end");
        Console.ReadKey();
    }

    private static void stream_read_write(string path, string iter, string input)
    {
        ProcessStartInfo start = new ProcessStartInfo();

        start.FileName = "C:\\Python27\\python.exe";
        start.Arguments = string.Format("{0} {1}", path, iter);
        start.UseShellExecute = false;
        start.RedirectStandardOutput = true;
        start.RedirectStandardInput = true;
        start.CreateNoWindow = true;

        using (Process process = Process.Start(start))
        using (StreamWriter writer = process.StandardInput)
        using (StreamReader reader = process.StandardOutput)
        {
            for (int i = 0; i < Convert.ToInt32(iter); i++)
            {
                Console.WriteLine("writing...");
                writer.WriteLine(input);
                writer.Flush();
                Console.WriteLine("written: " + input + "\n");

                Console.WriteLine("reading...");
                string result = reader.ReadLine();
                Console.WriteLine("read: " + result + "\n");
            }
        }
    }
}

The Python code looks like this:

import sys

iter = int(sys.argv[1])

for i in range(iter):
    input = raw_input()
    print (input)

And this is the output that I get:

writing...
written: Hello!

reading...

Strangely, when I remove the loops from both Python and C#, it works. (For one iteration)

writing...
written: Hello!

reading...
read: Hello!

end

It's not clear to me why this happens, or what the solution could be, so any help is much appreciated.

2

There are 2 answers

0
ThomasAlois On BEST ANSWER

I found a solution to my problem. I'm not really sure why this works, though. For C#:

using System;
using System.Diagnostics;
using System.IO;

public class Stream_Read_Write
{
    public static void Main()
    {
        string path = "C:\\Users\\thomas_wortmann\\Documents\\Python_Scripts\\io_test.py";
        string iter = "3";
        string input = "Hello";

        stream_read_write(path, iter, input);

        //Keep Console Open for Debug
        Console.Write("end");
        Console.ReadKey();
    }

    private static void stream_read_write(string path, string iter, string input)
    {
        ProcessStartInfo start = new ProcessStartInfo();

        start.FileName = "C:\\Python27\\python.exe";
        start.Arguments = string.Format("{0} {1}", path, iter);
        start.UseShellExecute = false;
        start.RedirectStandardOutput = true;
        start.RedirectStandardInput = true;
        start.CreateNoWindow = true;

        using (Process process = Process.Start(start))
        using (StreamWriter writer = process.StandardInput)
        using (StreamReader reader = process.StandardOutput)
        {
            for (int i = 0; i < Convert.ToInt32(iter); i++)
            {
                writer.WriteLine(input + i);
                Console.WriteLine("written: " + input + i);

                string result = null;

                while (result == null || result.Length == 0)
                { result = reader.ReadLine(); }

                Console.WriteLine("read: " + result + "\n");
            }
        }
    }
}

And the python code looks like this:

import sys

def reverse(input):
    return input [::-1]

iter = int(sys.argv[1])

for i in range(iter):
    input = sys.stdin.readline()
    print reverse(input)
    sys.stdout.flush()
0
AIR_Engineer On

This is a conventional stream problem. You have to “flush” the stream (e.g. stdout.flush() , where stdout is a stream object) in order to send the data no matter in C# or in Python. In C#, as I know, you have to execute stream.Close() to complete the flush itself, or you can wrap the stream with “using” and it send the data when the brackets is closed.

Edit: Btw, the stream is only available to one side at a time.