C#和Python之间的进程间通信
Posted
技术标签:
【中文标题】C#和Python之间的进程间通信【英文标题】:Interprocess communication between C# and Python 【发布时间】:2012-06-07 21:20:27 【问题描述】:我可以理解关于这个话题有很多问题,但没有一个能真正解决我的问题。所以在这里我展示了我的代码,我希望在这里指出我的错误。
我有一个用 C# 编写的程序,它应该调用一个 python 可执行文件/文件。第一个要求是我通过输入流将一个参数传递给 python 文件。这是我能做到的。我现在面临的真正问题是,我必须查看我的python文件是否正在打印“请输入argument_x”,我必须在我的C#代码中读取这个输出并检查它是否是argument_x,然后只将参数值写入输入流。下面是 C# 和 Python 的代码 sn-ps。
C#代码如下:
using System;
using System.IO;
using System.Diagnostics;
using System.ComponentModel;
namespace ConsoleApplication
class Program
static void Main(string[] args)
//Create a new process object
Process myProcess = new Process();
//Provide the start information for the process
myProcess.StartInfo.FileName = "python.exe";
myProcess.StartInfo.Arguments = "mytestpython.py";
myProcess.StartInfo.UseShellExecute = false;
myProcess.StartInfo.RedirectStandardInput = true;
myProcess.StartInfo.RedirectStandardOutput = true;
StreamReader myStreamReader;
StreamWriter myStreamWriter;
//Invoke the process from current process
myProcess.Start();
myStreamReader = myProcess.StandardOutput;
//Read the standard output of the spawned process.
string myString = myProcess.StandardOutput.ReadToEnd();
Console.WriteLine(myString);
if (myString.Contains("argument_x"))
myStreamWriter = myProcess.StandardInput;
String argument = "argument_value";
myStreamWriter.WriteLine(argument);
myProcess.WaitForExit();
myStreamWriter.Close();
myStreamReader.Close();
myProcess.Close();
mytestpython.py文件中的python程序如下:
import sys
import getpass
prompt_string = "Please enter argument_x"
if sys.stdin.isatty():
reqd_arg = getpass.getpass(prompt=prompt_string)
else:
print(prompt_string)
reqd_arg = sys.stdin.readline().rstrip()
请帮帮我,因为我觉得我已经正确编写了 90% 的代码,中间有一个小错误。提前感谢您的帮助。
【问题讨论】:
确保在每次输出后刷新,否则将无法正常工作。 @Dani 你能告诉我使用哪个函数吗?自动冲洗什么的?具体在哪里?myStreamWriter.WriteLine
之后的一行放入myStreamWriter.Flush();
@Dani 这并没有特别帮助。请提供现有问题的其他解决方案,如果有的话。同时我也在努力并试图了解可能导致问题的原因。
@Dani 终于找到了解决方案,我不得不同时更改 Python 和 C# 代码以适应这个问题。我必须在 Python 中做的是在 print 语句之后刷新标准输出。在 C# 结束时,只要我得到我想要的字符串,我就必须执行 Readline。对于我的操作,ReadToEnd 和 BeginOutputReadline 都不合适。很快就会发布工作代码。非常感谢您的投入:)
【参考方案1】:
当您执行myProcess.StandardOutput.ReadToEnd();
时,它会尝试读取您的 Python 程序的标准输出的末尾,这意味着它将等待 Python 程序完成执行并关闭其标准输出流,但它永远不会这样做,因为它正在等待来自 C# 程序的输入。这会导致死锁。
【讨论】:
你说的对代码,如果可能的话。 @PRC_noob 您需要逐个字符地阅读并尝试匹配您阅读的内容和您的期望。【参考方案2】:ReadToEnd()
在父进程等待子进程完成时很有用。在交互式进程通信的情况下,您应该真正考虑使用 BeginOutputReadLine
使用异步通信查看 MSDN 文档 here 以获得帮助
【讨论】:
@PRC_noob 请不要忘记给所有帮助您解决问题的人一些奖励(+1) :) 并接受您看到的与您找到的解决方案非常接近的答案; 【参考方案3】:我修改了 C# 代码以接受 CLI 参数并在提示符下传递密码,如下所示:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Diagnostics;
using System.ComponentModel;
namespace Stub
class Program
static void Main(string[] args)
// Declare variables and initialize
string passWord = string.Empty;
string processArgs = getArguments(args); //Call getArguments method
Console.Write("Please enter the system password : ");
passWord = readPassword(); //call readPassword method
Process p = new Process();
p.StartInfo.FileName = "myexe.exe";
p.StartInfo.Arguments = processArgs;
p.StartInfo.WorkingDirectory = "my_working_directory";
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardInput = true;
p.StartInfo.RedirectStandardOutput = true;
p.Start();
StreamWriter sw = p.StandardInput;
StreamReader sr = p.StandardOutput;
writePassword(sr, sw, "password", passWord);
sw.Close();
sr.Close();
p.WaitForExit();
p.Close();
static string getArguments(string[] args)
StringBuilder procArgs = new StringBuilder();
foreach (string arg in args)
procArgs.Append(arg);
procArgs.Append(" ");
return procArgs.ToString();
static void writePassword(StreamReader sr, StreamWriter sw, string keyWord, string passWord)
string mystring;
do
mystring = sr.ReadLine();
while (!mystring.Contains(keyWord));
if (mystring.Contains(keyWord))
sw.WriteLine(passWord);
else
sw.WriteLine("\r\n");
static string readPassword()
string pass = string.Empty;
ConsoleKeyInfo key;
do
key = Console.ReadKey(true);
if (key.Key != ConsoleKey.Backspace)
pass +=key.KeyChar;
Console.Write("*");
else
if (pass.Length > 0)
pass = pass.Substring(0, (pass.Length - 1));
Console.Write("\b \b");
while (key.Key != ConsoleKey.Enter);
return pass;
然后在 Python 中稍作修改:
import sys
import getpass
prompt_string = "Please enter password"
if sys.stdin.isatty():
reqd_arg = getpass.getpass(prompt=prompt_string)
else:
print(prompt_string)
sys.stdout.flush()
reqd_arg = sys.stdin.readline().rstrip()
瞧……那行得通!!!
【讨论】:
以上是关于C#和Python之间的进程间通信的主要内容,如果未能解决你的问题,请参考以下文章