C# 启动 Python 不能及时获取输出信息

问题描述:项目需要调用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()之后,可以时候获取输出信息了。

原文地址:https://www.cnblogs.com/zhangjd/p/12794582.html