与来自重定向 input/output/error 的 (Python) 进程交互时未命中 DataReceivedEvent
DataReceivedEvent not hit while Interacting with (Python) process from redirected input/output/error
我正在尝试使用标准输入和输出从 C# 控制 python 会话。
启动 Python 进程后,我希望继续向其发送命令并将输出接收到我的 WinForms 文本框。
在尝试了许多 SO 答案和 MSDN 之后,关于为什么 DataReceivedEvent
处理程序未被调用的任何建议?完整代码如下:
请注意,要从 Python 生成换行符,我在命令文本 import os;print os.linesep
中输入
using System;
using System.Diagnostics;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
private static Process InterProc;
public Form1()
{
InitializeComponent();
InterProc = new Process();
InitializeInterpreter();
}
private void InitializeInterpreter()
{
InterProc.StartInfo.UseShellExecute = false;
InterProc.StartInfo.FileName = @"C:\Python27\python.exe";
InterProc.StartInfo.RedirectStandardInput = true;
InterProc.StartInfo.RedirectStandardOutput = true;
InterProc.StartInfo.RedirectStandardError = true;
InterProc.StartInfo.CreateNoWindow = true;
InterProc.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
InterProc.OutputDataReceived += new DataReceivedEventHandler(InterProcOutputHandler);
bool started = InterProc.Start();
InterProc.BeginOutputReadLine();
}
private void AppendTextInBox(TextBox box, string text)
{
if (this.InvokeRequired)
{
this.Invoke((Action<TextBox, string>)AppendTextInBox, OutputTextBox, text);
}
else
{
box.Text += text;
}
}
private void InterProcOutputHandler(object sendingProcess, DataReceivedEventArgs outLine)
{
AppendTextInBox(OutputTextBox, outLine.Data + Environment.NewLine);
}
private void Enterbutton_Click(object sender, EventArgs e)
{
InterProc.StandardInput.WriteLine(CommandTextBox.Text);
}
}
}
这个答案是为那些登陆这里的人准备的,他们在 SO 上有很多答案。
最终与python会话交互的代码如下:
注意 1:使用“-i”参数调用 Python。 (参考下面的过程参数 -i
)
注 2:尝试从 std 错误冻结同步读取(Process.StandardError.ReadToEnd()
)。因此,std 输出流和错误流都需要提供处理程序回调 (参考下面的 InterProcOutputHandler
)
using System;
using System.Diagnostics;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
private static Process InterProc;
public Form1()
{
InitializeComponent();
InterProc = new Process();
InitializeInterpreter();
}
private void InitializeInterpreter()
{
InterProc.StartInfo.FileName = @"C:\Python27\python.exe";
InterProc.StartInfo.Arguments = @"-i"; // drops python into interactive mode after executing script if passed any
InterProc.StartInfo.UseShellExecute = false;
InterProc.StartInfo.RedirectStandardInput = true;
InterProc.StartInfo.RedirectStandardOutput = true;
InterProc.StartInfo.RedirectStandardError = true;
InterProc.StartInfo.CreateNoWindow = true;
InterProc.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
InterProc.OutputDataReceived += new DataReceivedEventHandler(InterProcOutputHandler);
InterProc.ErrorDataReceived += new DataReceivedEventHandler(InterProcOutputHandler);
bool started = InterProc.Start();
InterProc.BeginOutputReadLine();
InterProc.BeginErrorReadLine();
}
private void AppendTextInBox(TextBox box, string text)
{
if (InvokeRequired)
{
Invoke((Action<TextBox, string>)AppendTextInBox, OutputTextBox, text);
}
else
{
box.Text += text;
}
}
private void InterProcOutputHandler(object sendingProcess, DataReceivedEventArgs outLine)
{
AppendTextInBox(OutputTextBox, outLine.Data + Environment.NewLine);
}
private void Enterbutton_Click(object sender, EventArgs e)
{
InterProc.StandardInput.WriteLine(CommandTextBox.Text);
}
}
}
这可能会对上述解决方案不起作用的其他人有所帮助。
我一直遇到完全相同的问题并一直在努力解决,最终找到了这个问题和答案。
对我来说,StdError
via ErrorDataReceived
被触发错误输出,只是 Stdout
via OutputDataReceived
没有被触发。
我在 Linux (Raspberry Pi) 上是 运行 dotnet core,但我在 Windows 上也遇到了同样的问题 运行。
我的代码和vijiboy的回答基本一致,所以我在Python中添加了-i
选项,但没有任何区别!但这启发了我仔细研究 Python 选项,我发现了这个:
-u : force the stdout and stderr streams to be unbuffered;
this option has no effect on stdin; also PYTHONUNBUFFERED=x
所以在调用Python的时候加上-u(去掉-i)就解决了问题,终于触发了OutputDataReceived
!
我正在尝试使用标准输入和输出从 C# 控制 python 会话。
启动 Python 进程后,我希望继续向其发送命令并将输出接收到我的 WinForms 文本框。
在尝试了许多 SO 答案和 MSDN 之后,关于为什么 DataReceivedEvent
处理程序未被调用的任何建议?完整代码如下:
请注意,要从 Python 生成换行符,我在命令文本 import os;print os.linesep
using System;
using System.Diagnostics;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
private static Process InterProc;
public Form1()
{
InitializeComponent();
InterProc = new Process();
InitializeInterpreter();
}
private void InitializeInterpreter()
{
InterProc.StartInfo.UseShellExecute = false;
InterProc.StartInfo.FileName = @"C:\Python27\python.exe";
InterProc.StartInfo.RedirectStandardInput = true;
InterProc.StartInfo.RedirectStandardOutput = true;
InterProc.StartInfo.RedirectStandardError = true;
InterProc.StartInfo.CreateNoWindow = true;
InterProc.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
InterProc.OutputDataReceived += new DataReceivedEventHandler(InterProcOutputHandler);
bool started = InterProc.Start();
InterProc.BeginOutputReadLine();
}
private void AppendTextInBox(TextBox box, string text)
{
if (this.InvokeRequired)
{
this.Invoke((Action<TextBox, string>)AppendTextInBox, OutputTextBox, text);
}
else
{
box.Text += text;
}
}
private void InterProcOutputHandler(object sendingProcess, DataReceivedEventArgs outLine)
{
AppendTextInBox(OutputTextBox, outLine.Data + Environment.NewLine);
}
private void Enterbutton_Click(object sender, EventArgs e)
{
InterProc.StandardInput.WriteLine(CommandTextBox.Text);
}
}
}
这个答案是为那些登陆这里的人准备的,他们在 SO 上有很多答案。
最终与python会话交互的代码如下:
注意 1:使用“-i”参数调用 Python。 (参考下面的过程参数 -i
)
注 2:尝试从 std 错误冻结同步读取(Process.StandardError.ReadToEnd()
)。因此,std 输出流和错误流都需要提供处理程序回调 (参考下面的 InterProcOutputHandler
)
using System;
using System.Diagnostics;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
private static Process InterProc;
public Form1()
{
InitializeComponent();
InterProc = new Process();
InitializeInterpreter();
}
private void InitializeInterpreter()
{
InterProc.StartInfo.FileName = @"C:\Python27\python.exe";
InterProc.StartInfo.Arguments = @"-i"; // drops python into interactive mode after executing script if passed any
InterProc.StartInfo.UseShellExecute = false;
InterProc.StartInfo.RedirectStandardInput = true;
InterProc.StartInfo.RedirectStandardOutput = true;
InterProc.StartInfo.RedirectStandardError = true;
InterProc.StartInfo.CreateNoWindow = true;
InterProc.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
InterProc.OutputDataReceived += new DataReceivedEventHandler(InterProcOutputHandler);
InterProc.ErrorDataReceived += new DataReceivedEventHandler(InterProcOutputHandler);
bool started = InterProc.Start();
InterProc.BeginOutputReadLine();
InterProc.BeginErrorReadLine();
}
private void AppendTextInBox(TextBox box, string text)
{
if (InvokeRequired)
{
Invoke((Action<TextBox, string>)AppendTextInBox, OutputTextBox, text);
}
else
{
box.Text += text;
}
}
private void InterProcOutputHandler(object sendingProcess, DataReceivedEventArgs outLine)
{
AppendTextInBox(OutputTextBox, outLine.Data + Environment.NewLine);
}
private void Enterbutton_Click(object sender, EventArgs e)
{
InterProc.StandardInput.WriteLine(CommandTextBox.Text);
}
}
}
这可能会对上述解决方案不起作用的其他人有所帮助。 我一直遇到完全相同的问题并一直在努力解决,最终找到了这个问题和答案。
对我来说,StdError
via ErrorDataReceived
被触发错误输出,只是 Stdout
via OutputDataReceived
没有被触发。
我在 Linux (Raspberry Pi) 上是 运行 dotnet core,但我在 Windows 上也遇到了同样的问题 运行。
我的代码和vijiboy的回答基本一致,所以我在Python中添加了-i
选项,但没有任何区别!但这启发了我仔细研究 Python 选项,我发现了这个:
-u : force the stdout and stderr streams to be unbuffered; this option has no effect on stdin; also PYTHONUNBUFFERED=x
所以在调用Python的时候加上-u(去掉-i)就解决了问题,终于触发了OutputDataReceived
!