dotnet 中使用 Process 来启用子进程是很常见的操作,还可以配置为重定向输入输出流,对操作命令行程序很方便。一般的使用代码如下:
static void Main(string[] args)
{
ProcessStartInfo startInfo = new ProcessStartInfo("app.exe", "args");
startInfo.UseShellExecute = false;
startInfo.RedirectStandardOutput = true;
startInfo.RedirectStandardError = true;
Process process = new Process() { StartInfo = startInfo };
process.EnableRaisingEvents = true;
process.OutputDataReceived += Process_OutputDataReceived;
process.ErrorDataReceived += Process_ErrorDataReceived;
process.Exited += Process_Exited;
process.Start();
process.BeginOutputReadLine();
process.BeginErrorReadLine();
process.WaitForExit();
}
private static void Process_Exited(object sender, EventArgs e)
{
Console.WriteLine($"ExitCode {((Process)sender).ExitCode}");
}
private static void Process_ErrorDataReceived(object sender, DataReceivedEventArgs e)
{
Console.WriteLine($"Error: {e.Data}");
}
private static void Process_OutputDataReceived(object sender, DataReceivedEventArgs e)
{
Console.WriteLine($"{e.Data}");
}
对于调用普通的程序,这样就已经足够了。但用来调用 python 程序就很奇怪。(测试环境为 python 3.7 )
import time
for i in range(100):
print('message %d ' % i)
time.sleep(0.2)
对于上面这个 python 脚本,直接在 shell 中运行的话,会接连输出一串文本行,每 0.2 秒一次。但通过下面的脚本去调用的话,则等待了若干秒(100 * 0.2 = 20)之后,才会把结果一股脑输出。
ProcessStartInfo startInfo = new ProcessStartInfo("python", "a.py");
查了资料,原来 python 会默认 buffer 标准输出流,导致这个现象,解决方法很简单,加一个 -u 参数即可。
ProcessStartInfo startInfo = new ProcessStartInfo("python", "-u a.py");
命令行说明:
-u
Force the stdout and stderr streams to be unbuffered. This option has no effect on the stdin stream.