Я пытаюсь запустить процесс в интерактивном режиме, используя ...
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