Home > Enterprise >  How to run 2 process and exchange input/output between them multiple times?
How to run 2 process and exchange input/output between them multiple times?

Time:06-04

I'm trying to do something like this:

Future<String> getOutAndAnswer(testcase) async {
  Process python = await Process.start('python', ['tasks/histogram/run.py']);

  Process java = await Process.start('java', ['solutions/Histogram.java']);

  String results = "";

  for(int i = 0; i < testcase; i  ){
    final String out = await python.stdout.transform(utf8.decoder).first;

    java.stdin.writeln(out);

    final String answer = await java.stdout.transform(utf8.decoder).first;

    python.stdin.writeln(answer);

    results  = "($out, $answer)";
  }

  return results;
}

Basically, the python program is responsible for generating the input of each test case, then the java program will take the input and return the answer, which is sent to the python program to check if it's correct or not, and so on for every test case.

But when I try to use the above code I get an error saying I've already listened to the stream once:

Exception has occurred.
StateError (Bad state: Stream has already been listened to.)

Python program:

import os

CASE_DIR = os.path.join(os.path.dirname(__file__), "cases")

test_cases = next(os.walk(CASE_DIR))[2]

print(len(test_cases))
for case in sorted(test_cases):
    with open(os.path.join(CASE_DIR, case), 'r') as f:
        print(f.readline(), end='', flush=True)
        f.readline()
        
        expected_output = f.readline()

        user_output = input()
        
        if expected_output != user_output:
            raise ValueError("Wrong answer!")

print("EXIT", flush=True)

Java program:

public class Histogram {

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);

        int t = scanner.nextInt();
        for (int i = 0; i < t; i  ) {
            String input = scanner.nextLine();

            String answer = calculateAnswer(input);

            System.out.println(answer);
        }
    }
}

CodePudding user response:

Your issue is with .first which is going to listen to the stream, get the first element, and then immediately stop listening to the stream. See the documentation here: https://api.dart.dev/stable/2.17.3/dart-async/Stream/first.html

You should instead listen once and define an onData method to perform the steps. See the documentation for .listen() here: https://api.dart.dev/stable/2.17.3/dart-async/Stream/listen.html

CodePudding user response:

You could try wrapping the stdout streams in StreamIterator<String>. You will have to give it a try to verify, but I think this is what you are looking for.

Future<String> getOutAndAnswer(int testcase) async {
  Process python = await Process.start('python', ['tasks/histogram/run.py']);
  Process java = await Process.start('java', ['solutions/Histogram.java']);

  String results = "";

  StreamIterator<String> pythonIterator = StreamIterator(
      python.stdout.transform(utf8.decoder).transform(LineSplitter()));
  StreamIterator<String> javaIterator = StreamIterator(
      java.stdout.transform(utf8.decoder).transform(LineSplitter()));

  for (int i = 0; i < testcase; i  ) {
    if (await pythonIterator.moveNext()) {
      final String out = pythonIterator.current;
      if (out == 'EXIT') {
        break;
      }

      java.stdin.writeln(out);

      if (await javaIterator.moveNext()) {
        final String answer = javaIterator.current;

        python.stdin.writeln(answer);

        results  = "($out, $answer)";
      }
    }
  }

  await pythonIterator.cancel();
  await javaIterator.cancel();
  return results;
}

You may need to add the following imports:

import 'dart:async';
import 'dart:convert';
  • Related