我有C#代码正在启动一个恰好是运行脚本的python解释器的进程。目标是将该解释器的stdin和stdout重定向为与脚本进行进程间通信的方法。代码如下:
String py_path = @"C:\Anaconda3\python.exe";
String script_path = @"<python script>";
String working_dir = @"<directory of python script>";
// Create new process start info
ProcessStartInfo myProcessStartInfo = new ProcessStartInfo(py_path);
// redirect standard in and out
myProcessStartInfo.UseShellExecute = false;
myProcessStartInfo.RedirectStandardOutput = true;
myProcessStartInfo.RedirectStandardInput = true;
myProcessStartInfo.Arguments = script_path;
myProcessStartInfo.WorkingDirectory = working_dir;
Process myProcess = new Process();
// assign start information to the process
myProcess.StartInfo = myProcessStartInfo;
// start process
myProcess.Start();
//read one line from stdout
StreamReader myStreamReader = myProcess.StandardOutput;
String return_value_1 = myStreamReader.ReadLine();
if(return_value1 == null)
Print("Null return value");
else
Print(return_value1);
此代码失败(return_value1
为null
),即使python脚本执行的第一件事是在stdout上打印一行。
但是,如果我注释掉标准输入的重定向(在本例中未触及),如下所示:
String py_path = @"C:\Anaconda3\python.exe";
String script_path = @"<python script>";
String working_dir = @"<directory of python script>";
// Create new process start info
ProcessStartInfo myProcessStartInfo = new ProcessStartInfo(py_path);
// redirect standard in and out
myProcessStartInfo.UseShellExecute = false;
myProcessStartInfo.RedirectStandardOutput = true;
//myProcessStartInfo.RedirectStandardInput = true;
myProcessStartInfo.Arguments = script_path;
myProcessStartInfo.WorkingDirectory = working_dir;
Process myProcess = new Process();
// assign start information to the process
myProcess.StartInfo = myProcessStartInfo;
// start process
myProcess.Start();
//read one line from stdout
StreamReader myStreamReader = myProcess.StandardOutput;
String return_value_1 = myStreamReader.ReadLine();
if(return_value1 == null)
Print("Null return value");
else
Print(return_value1);
然后代码打印python脚本写入stdout的第一行,正如我所料。
显然,以某种方式重定向stdin会导致重定向的stdout的ReadLine()
返回null,但我不理解这种交互。
此处描述的死锁问题有可能存在: https://msdn.microsoft.com/en-us/library/system.diagnostics.processstartinfo.redirectstandardoutput.aspx 以某种方式参与其中,但我不会立即看到情况如何。
答案 0 :(得分:0)
首次使用例子
myProcess.StandardInput.Close();
之后的myProcess.Start()
。您应该在获得输出之前发送所有输入。
虽然您想要StandardError的输出和错误
string py_path = @"C:\Anaconda3\python.exe";
string script_path = @"<python script>";
string working_dir = @"<directory of python script>";
var processStartInfo = new ProcessStartInfo(py_path)
{
Arguments = script_path,
WorkingDirectory = working_dir,
UseShellExecute = false,
CreateNoWindow = true,
RedirectStandardInput = true,
RedirectStandardOutput = true,
RedirectStandardError = true
};
var process = new Process { StartInfo = processStartInfo };
process.Start();
process.StandardInput.Close();
var stdOut = Task.Factory.StartNew(() => process.StandardOutput.ReadToEnd());
var stdErr = Task.Factory.StartNew(() => process.StandardError.ReadToEnd());
process.WaitForExit();
var output = stdOut.Result;
var error = stdErr.Result
我使用了Task,因为如果stdout或stderr有大量数据,缓冲区可能已满,应用程序将挂起
我还添加了一种异步退出/错误的方法,你可以写入输入
string py_path = @"C:\Anaconda3\python.exe";
string script_path = @"<python script>";
string working_dir = @"<directory of python script>";
var processStartInfo = new ProcessStartInfo(py_path)
{
Arguments = script_path,
WorkingDirectory = working_dir,
UseShellExecute = false,
CreateNoWindow = true,
RedirectStandardInput = true,
RedirectStandardOutput = true,
RedirectStandardError = true,
};
var process = new Process { StartInfo = processStartInfo };
var outputBuffer = new StringBuilder();
var errorBuffer = new StringBuilder();
process.OutputDataReceived += (s, ea) => outputBuffer.AppendLine(ea.Data);
process.ErrorDataReceived += (s, ea) => errorBuffer.AppendLine(ea.Data);
process.Start();
process.BeginOutputReadLine();
process.BeginErrorReadLine();
process.StandardInput.WriteLine();
// from now on can write what ever to StandardInput and data will be into output
// and error buffer. Sometimes might want synchronization between read and write
// also might want to empty buffers