Как выполнить другой процесс в интерактивном режиме - PullRequest
0 голосов
/ 02 мая 2020

Я пытаюсь запустить процесс в интерактивном режиме, используя ...

    Process.start()

..., но у меня возникают проблемы с буферизацией. Я хотел бы получать выходные данные построчно, но выходные данные из stockfi sh буферизируются.

git: См. https://bitbucket.org/oakstair/dart_process/src/master/

Нет из методов запуска ниже работает для меня. Я запускаю это в OsX.

Ожидаемый вывод получен для двух методов запуска, но буферизован.

    import 'dart:convert';
    import 'dart:io';

    typedef OnLine = Function(String line);

    /// Run stockfish as a remote process.
    class Stockfish {

      Process _process;

      Stockfish();

      void startBinaryDirect_WithLineSplitting(OnLine handleReply, [OnLine handleError]) async {
        await Process.start('./stockfish', []).then((p) {
          _process = p;
          _process.stdout.transform(Utf8Decoder()).transform(LineSplitter())
              .listen(handleReply);
          _process.stderr.transform(Utf8Decoder()).transform(LineSplitter())
              .listen(handleError);
        });
      }

      void startBinaryDirect_JustRedirect(OnLine handleReply, [OnLine handleError]) async {
        await Process.start('./stockfish', []).then((p) {
          _process = p;
          stdout.addStream(_process.stdout);
          stderr.addStream(_process.stderr);
        });
      }

      void startUsingStdbuf_WithLineSplitting(OnLine handleReply, [OnLine handleError]) async {

        await Process.start('stdbuf', ['-oL', '-eL', './stockfish'], runInShell: true).then((p) {
          _process = p;
          _process.stdout.transform(Utf8Decoder()).transform(LineSplitter())
              .listen(handleReply);
          _process.stderr.transform(Utf8Decoder()).transform(LineSplitter())
              .listen(handleError);
        });
      }

      /// Stop engine and kill process.
      void stop() {
        _process.kill();
      }

      void sendCommand(String cmd) {
        _process.stdin.writeln(cmd);
      }

    }

Вот мой тестовый код

    import 'dart:io';

    import 'package:dart_process/stockfish.dart';
    import 'package:test/test.dart';

    // Note: We are starting stockfish (in various ways) plus sending some commands to it. The expected output is
    String expectedResult = '''
    Stockfish 310320 64 by T. Romstad, M. Costalba, J. Kiiski, G. Linscott
    readyok
    id name Stockfish 310320 64
    id author T. Romstad, M. Costalba, J. Kiiski, G. Linscott

    option name Debug Log File type string default
    option name Contempt type spin default 24 min -100 max 100
    option name Analysis Contempt type combo default Both var Off var White var Black var Both
    option name Threads type spin default 1 min 1 max 512
    option name Hash type spin default 16 min 1 max 131072
    option name Clear Hash type button
    option name Ponder type check default false
    option name MultiPV type spin default 1 min 1 max 500
    option name Skill Level type spin default 20 min 0 max 20
    option name Move Overhead type spin default 30 min 0 max 5000
    option name Minimum Thinking Time type spin default 20 min 0 max 5000
    option name Slow Mover type spin default 84 min 10 max 1000
    option name nodestime type spin default 0 min 0 max 10000
    option name UCI_Chess960 type check default false
    option name UCI_AnalyseMode type check default false
    option name UCI_LimitStrength type check default false
    option name UCI_Elo type spin default 1350 min 1350 max 2850
    option name SyzygyPath type string default <empty>
    option name SyzygyProbeDepth type spin default 1 min 1 max 100
    option name Syzygy50MoveRule type check default true
    option name SyzygyProbeLimit type spin default 7 min 0 max 7
    uciok
    readyok
    ''';

    typedef StartFunction = Function(OnLine onDataLine, OnLine onErrorLine);

    void main() {
      test('startBinaryDirect', () async {

        Future<void> testStart(Stockfish sf, StartFunction start) async {
          DateTime startedAt = DateTime.now();

          int millis() => DateTime.now().difference(startedAt).inMilliseconds;
          await start((String line) => print('${millis()}: $line'),
              (String error) => print('${millis()}: ERROR: $error'));

          // -- Send some commands to stockfish. --
          sf.sendCommand('isready');
          sf.sendCommand('uci');
          sf.sendCommand('isready');

          // -- Give stockfish more than enough time to process the commands. --
          sleep(Duration(seconds: 2));
        }

        Stockfish sf1 = Stockfish();
        await testStart(sf1, sf1.startBinaryDirect_WithLineSplitting);
        print('Done startBinaryDirect_WithLineSplitting');

        Stockfish sf2 = Stockfish();
        await testStart(sf2, sf2.startBinaryDirect_JustRedirect);
        print('Done startBinaryDirect_JustRedirect');

        Stockfish sf3 = Stockfish();
        await testStart(sf3, sf3.startUsingStdbuf_WithLineSplitting);
        print('Done startUsingStdbuf_WithLineSplitting');

        sleep(Duration(seconds: 3));
      });
    }

И вот мой тестовый вывод

    Done startBinaryDirect_WithLineSplitting
    2046: Stockfish 310320 64 by T. Romstad, M. Costalba, J. Kiiski, G. Linscott
    2046: readyok
    2046: id name Stockfish 310320 64
    2046: id author T. Romstad, M. Costalba, J. Kiiski, G. Linscott
    2046: 
    2046: option name Debug Log File type string default 
    2046: option name Contempt type spin default 24 min -100 max 100
    2046: option name Analysis Contempt type combo default Both var Off var White var Black var Both
    2046: option name Threads type spin default 1 min 1 max 512
    2046: option name Hash type spin default 16 min 1 max 131072
    2046: option name Clear Hash type button
    2046: option name Ponder type check default false
    2046: option name MultiPV type spin default 1 min 1 max 500
    2046: option name Skill Level type spin default 20 min 0 max 20
    2046: option name Move Overhead type spin default 30 min 0 max 5000
    2046: option name Minimum Thinking Time type spin default 20 min 0 max 5000
    2046: option name Slow Mover type spin default 84 min 10 max 1000
    2046: option name nodestime type spin default 0 min 0 max 10000
    2046: option name UCI_Chess960 type check default false
    2046: option name UCI_AnalyseMode type check default false
    2046: option name UCI_LimitStrength type check default false
    2046: option name UCI_Elo type spin default 1350 min 1350 max 2850
    2046: option name SyzygyPath type string default <empty>
    2046: option name SyzygyProbeDepth type spin default 1 min 1 max 100
    2046: option name Syzygy50MoveRule type check default true
    2046: option name SyzygyProbeLimit type spin default 7 min 0 max 7
    2046: uciok
    2046: readyok
    Done startBinaryDirect_JustRedirect
    Stockfish 310320 64 by T. Romstad, M. Costalba, J. Kiiski, G. Linscott
    readyok
    id name Stockfish 310320 64
    id author T. Romstad, M. Costalba, J. Kiiski, G. Linscott

    option name Debug Log File type string default 
    option name Contempt type spin default 24 min -100 max 100
    option name Analysis Contempt type combo default Both var Off var White var Black var Both
    option name Threads type spin default 1 min 1 max 512
    option name Hash type spin default 16 min 1 max 131072
    option name Clear Hash type button
    option name Ponder type check default false
    option name MultiPV type spin default 1 min 1 max 500
    option name Skill Level type spin default 20 min 0 max 20
    option name Move Overhead type spin default 30 min 0 max 5000
    option name Minimum Thinking Time type spin default 20 min 0 max 5000
    option name Slow Mover type spin default 84 min 10 max 1000
    option name nodestime type spin default 0 min 0 max 10000
    option name UCI_Chess960 type check default false
    option name UCI_AnalyseMode type check default false
    option name UCI_LimitStrength type check default false
    option name UCI_Elo type spin default 1350 min 1350 max 2850
    option name SyzygyPath type string default <empty>
    option name SyzygyProbeDepth type spin default 1 min 1 max 100
    option name Syzygy50MoveRule type check default true
    option name SyzygyProbeLimit type spin default 7 min 0 max 7
    uciok
    readyok
    Done startUsingStdbuf_WithLineSplitting
    5015: Stockfish 310320 64 by T. Romstad, M. Costalba, J. Kiiski, G. Linscott
    5015: readyok
    5015: id name Stockfish 310320 64
    5015: id author T. Romstad, M. Costalba, J. Kiiski, G. Linscott
    5015: 
    5015: option name Debug Log File type string default 
    5015: option name Contempt type spin default 24 min -100 max 100
    5015: option name Analysis Contempt type combo default Both var Off var White var Black var Both
    5015: option name Threads type spin default 1 min 1 max 512
    5015: option name Hash type spin default 16 min 1 max 131072
    5015: option name Clear Hash type button

    Process finished with exit code 0
...