问题描述:项目需要调用python的一套程序去处理一些问题,然后我用Process 类启动一个进程,调用了python程序,通过实时输出获取执行进度信息,但是执行的时候我发现输出并不是实时的。
1、调用外部程序的代码是这样的
public static Process CommitCommand(string commandStr, string workingDir, Action<DataReceivedEventArgs> action) { var logger = LogManager.GetCurrentClassLogger(); try { logger.Debug("Get into CommitCommand"); Process process = new Process(); process.StartInfo.FileName = commandStr.Substring(0, commandStr.IndexOf(" ")).Trim(); var pathDir = Environment.GetEnvironmentVariable("PATH").Split(RuntimeInformation.IsOSPlatform(OSPlatform.Linux) ? ":" : ";", StringSplitOptions.RemoveEmptyEntries) .FirstOrDefault(s => File.Exists(Path.Combine(s, process.StartInfo.FileName)) || File.Exists(Path.Combine(s, process.StartInfo.FileName + ".exe"))); if (string.IsNullOrEmpty(pathDir)) { process.StartInfo.FileName = Path.GetFullPath(process.StartInfo.FileName, workingDir); } process.StartInfo.Arguments = commandStr.Substring(commandStr.IndexOf(" ")).Trim(); process.StartInfo.WorkingDirectory = string.IsNullOrWhiteSpace(workingDir) ? process.StartInfo.WorkingDirectory : workingDir; process.StartInfo.CreateNoWindow = true; process.StartInfo.ErrorDialog = false; process.StartInfo.UseShellExecute = false; process.StartInfo.RedirectStandardOutput = true; process.StartInfo.RedirectStandardError = true; process.StartInfo.RedirectStandardInput = true; process.ErrorDataReceived += (sender, args) => { action(args); logger.Error($"ErrorDataReceived:commandStr:{commandStr}. workingDir:{workingDir}. Error:{args.Data}"); }; process.EnableRaisingEvents = true; process.OutputDataReceived += (sender, args) => { action(args); logger.Debug($"OutputDataReceived:{args.Data}"); }; process.Exited += (sender, args) => { logger.Debug("程序退出!"); logger.Error($"Exited:commandStr:{commandStr}. workingDir:{workingDir}"); }; process.Start(); process.StandardInput.AutoFlush = true; process.BeginErrorReadLine(); process.BeginOutputReadLine(); logger.Debug("Sign out CommitCommand"); return process; } catch (Exception e) { logger.Error(e, "process can not start."); logger.Debug(e.Message); return null; } }
2、问题分析
正常情况下,每次输出都会触发OutputDataReceived事件,但是实际上的输出是在执行完成之后一次性输出的,网上搜索后发现只有 C#编写的程序才能直接正常运行,其他语言编写的程序都会遇到这个问题。而解决办法的思路都是一样的,在不同语言中调用打印方法后,接着调用一个类似 flush 的方法,比如在 python中就是 sys.stdout.flush()方法,这样就能每次 print之后触发 OutputDataReceived 事件了。
3、解决办法
然后我在python的输出代码下,加了sys.stdout.flush()之后,可以时候获取输出信息了。