某些 Python 命令未在 Stdout 中捕获
我编写了一个简单的程序来捕获并执行命令行 Python 脚本,但有一个问题。尽管我的程序捕获了标准输出,但传递给 Python 输入函数的文本并未写入我的程序。
例如: Python 脚本:
import sys
print("Hello, World!")
x = input("Please enter a number: ")
print(x)
print("This work?")
会写“Hello, World!”然后停下来。当我向它传递一个数字时,它会继续写“请输入数字:3”。到底是怎么回事?有什么解决办法吗?我的 C# 如下:
public partial class PyCon : Window
{
public string strPythonPath;
public string strFile;
public string strArguments;
private StreamWriter sw;
public PyCon(string pythonpath, string file, string args)
{
strPythonPath = pythonpath;
strFile = file;
strArguments = args;
InitializeComponent();
Process p = new Process();
p.StartInfo.FileName = strPythonPath;
p.StartInfo.Arguments = "\"" + strFile + "\" " + strArguments;
p.StartInfo.UseShellExecute = false;
p.StartInfo.CreateNoWindow = true;
p.StartInfo.RedirectStandardInput = true;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.RedirectStandardError = true;
p.OutputDataReceived += new DataReceivedEventHandler(p_OutputDataReceived);
p.ErrorDataReceived += new DataReceivedEventHandler(p_ErrorDataReceived);
p.Start();
p.BeginOutputReadLine();
p.BeginErrorReadLine();
sw = p.StandardInput;
}
private void p_OutputDataReceived(object sendingProcess, DataReceivedEventArgs received) {
if (!String.IsNullOrEmpty(received.Data)) {
AppendConsole(received.Data);
}
}
private void p_ErrorDataReceived(object sendingProcess, DataReceivedEventArgs received) {
if (!String.IsNullOrEmpty(received.Data)) {
AppendConsole(received.Data);
}
}
private void AppendConsole(string message) {
if (!txtConsole.Dispatcher.CheckAccess()) {
txtConsole.Dispatcher.Invoke(DispatcherPriority.Normal, (System.Windows.Forms.MethodInvoker)delegate() { txtConsole.AppendText(message + "\n"); });
} else {
//Format text
message = message.Replace("\n", Environment.NewLine);
txtConsole.AppendText(message + "\n");
}
}
private void txtInput_KeyUp(object sender, KeyEventArgs e) {
if (e.Key != Key.Enter) return;
sw.WriteLine(txtInput.Text);
txtInput.Text = "";
}
}
编辑:经过此线程的大量研究和帮助,我得出的结论是,问题在于 Python 输入命令未调用 C# DataReceivedEventHandler。除了更改脚本之外,可能没有其他解决方案。如果是这种情况,我将做出包含已接受的更改的答案。谢谢你们的帮助,伙计们!
I've written a simple program that captures and executes command line Python scripts, but there is a problem. The text passed to a Python input function isn't written to my program despite my program capturing stdout.
For example:
The Python script:
import sys
print("Hello, World!")
x = input("Please enter a number: ")
print(x)
print("This work?")
Would write "Hello, World!" then stop. When I pass it a number it would continue on writing "Please enter a number: 3". What is going on? Any solutions? My C# is as follows:
public partial class PyCon : Window
{
public string strPythonPath;
public string strFile;
public string strArguments;
private StreamWriter sw;
public PyCon(string pythonpath, string file, string args)
{
strPythonPath = pythonpath;
strFile = file;
strArguments = args;
InitializeComponent();
Process p = new Process();
p.StartInfo.FileName = strPythonPath;
p.StartInfo.Arguments = "\"" + strFile + "\" " + strArguments;
p.StartInfo.UseShellExecute = false;
p.StartInfo.CreateNoWindow = true;
p.StartInfo.RedirectStandardInput = true;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.RedirectStandardError = true;
p.OutputDataReceived += new DataReceivedEventHandler(p_OutputDataReceived);
p.ErrorDataReceived += new DataReceivedEventHandler(p_ErrorDataReceived);
p.Start();
p.BeginOutputReadLine();
p.BeginErrorReadLine();
sw = p.StandardInput;
}
private void p_OutputDataReceived(object sendingProcess, DataReceivedEventArgs received) {
if (!String.IsNullOrEmpty(received.Data)) {
AppendConsole(received.Data);
}
}
private void p_ErrorDataReceived(object sendingProcess, DataReceivedEventArgs received) {
if (!String.IsNullOrEmpty(received.Data)) {
AppendConsole(received.Data);
}
}
private void AppendConsole(string message) {
if (!txtConsole.Dispatcher.CheckAccess()) {
txtConsole.Dispatcher.Invoke(DispatcherPriority.Normal, (System.Windows.Forms.MethodInvoker)delegate() { txtConsole.AppendText(message + "\n"); });
} else {
//Format text
message = message.Replace("\n", Environment.NewLine);
txtConsole.AppendText(message + "\n");
}
}
private void txtInput_KeyUp(object sender, KeyEventArgs e) {
if (e.Key != Key.Enter) return;
sw.WriteLine(txtInput.Text);
txtInput.Text = "";
}
}
Edit: After a lot of research and help from this thread, I've come to the conclusion that the problem is with the Python input command not calling the C# DataReceivedEventHandler. There may not be a solution to this besides scripting changes. If that is the case, I'll make the answer containing those changes as accepted. Thanks for the help, guys!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
听起来像 Python i/o 是行缓冲的,即等待 CRLF 然后立即发送整行。您可以尝试将其关闭(python -u myscript.py,或设置PYTHONUNBUFFERED环境变量)或使用如下方法解决它:
Smells like the Python i/o is line buffered, i.e. waits for a CRLF then sends a whole line at once. You could try turning that off (python -u myscript.py, or set the PYTHONUNBUFFERED environment variable) or work around it with something like this:
很难说,因为我使用的是 python 2.6,而你似乎使用的是 3.x,而且我也已经有一段时间没有用 c# 编程了,但我的猜测是这一行:
正在发送“3”加上 Windows 新行特点。
尝试:
这只会发送一个正常的 换行符 而不是 Windows 回车符,这可能是问题所在。确保在处理像这样复杂的流通信时始终保持 Flush!
还有一件事,确保您可以在命令提示符下重定向它。程序员常常尝试同时做所有事情,但却陷入困境:
如果它在那里不起作用,那么它在 C# 中也不起作用。祝你好运
It's difficult to tell because I'm using python 2.6 and you appear to be using 3.x, and I also have not programmed in c# for quite awhile but my guess is that this line:
Is sending "3" plus a windows new line character.
Try:
This will just send a normal newline instead of a windows carriage return which may be the issue. Make sure you always Flush when dealing with complicated stream communication like this!
One more thing, make sure you can just redirect this at the command prompt. Too often programmers try to do everything at the same time and get stuck:
If it doesn't work there, it's not going to work in C#. Good luck