问题:如何从C#运行Python脚本?
之前曾在不同程度上提出过这样的问题,但我觉得还没有以简明的方式回答,因此我再次提出。
我想在Python中运行脚本。可以说是这样的:
if __name__ == '__main__':
with open(sys.argv[1], 'r') as f:
s = f.read()
print s
它获取文件位置,读取它,然后打印其内容。没那么复杂。
好吧,那我该如何在C#中运行它呢?
这就是我现在所拥有的:
private void run_cmd(string cmd, string args)
{
ProcessStartInfo start = new ProcessStartInfo();
start.FileName = cmd;
start.Arguments = args;
start.UseShellExecute = false;
start.RedirectStandardOutput = true;
using (Process process = Process.Start(start))
{
using (StreamReader reader = process.StandardOutput)
{
string result = reader.ReadToEnd();
Console.Write(result);
}
}
}
当我传递code.py
位置as cmd
和filename
位置as args
无效时。有人告诉我,我应该通过python.exe
的cmd
,然后code.py filename
作为args
。
我已经寻找了一段时间,只能找到建议使用IronPython之类的人。但是必须有一种从C#调用Python脚本的方法。
一些澄清:
我需要从C#运行它,我需要捕获输出,并且不能使用IronPython或其他任何东西。无论您有什么技巧,都可以。
PS:我正在运行的实际Python代码要复杂得多,并且它返回我在C#中需要的输出,并且C#代码将不断调用Python代码。
假设这是我的代码:
private void get_vals()
{
for (int i = 0; i < 100; i++)
{
run_cmd("code.py", i);
}
}
This sort of question has been asked before in varying degrees, but I feel it has not been answered in a concise way and so I ask it again.
I want to run a script in Python. Let’s say it’s this:
if __name__ == '__main__':
with open(sys.argv[1], 'r') as f:
s = f.read()
print s
Which gets a file location, reads it, then prints its contents. Not so complicated.
Okay, so how do I run this in C#?
This is what I have now:
private void run_cmd(string cmd, string args)
{
ProcessStartInfo start = new ProcessStartInfo();
start.FileName = cmd;
start.Arguments = args;
start.UseShellExecute = false;
start.RedirectStandardOutput = true;
using (Process process = Process.Start(start))
{
using (StreamReader reader = process.StandardOutput)
{
string result = reader.ReadToEnd();
Console.Write(result);
}
}
}
When I pass the code.py
location as cmd
and the filename
location as args
it doesn’t work. I was told I should pass python.exe
as the cmd
, and then code.py filename
as the args
.
I have been looking for a while now and can only find people suggesting to use IronPython or such. But there must be a way to call a Python script from C#.
Some clarification:
I need to run it from C#, I need to capture the output, and I can’t use IronPython or anything else. Whatever hack you have will be fine.
P.S.: The actual Python code I’m running is much more complex than this, and it returns output which I need in C#, and the C# code will be constantly calling the Python code.
Pretend this is my code:
private void get_vals()
{
for (int i = 0; i < 100; i++)
{
run_cmd("code.py", i);
}
}
回答 0
它不起作用的原因是因为您有UseShellExecute = false
。
如果不使用外壳,则必须以方式提供python可执行文件的完整路径FileName
,并构建Arguments
字符串以提供脚本和要读取的文件。
另请注意,RedirectStandardOutput
除非您不能这样做UseShellExecute = false
。
我不太确定应如何为python格式化参数字符串,但是您将需要以下内容:
private void run_cmd(string cmd, string args)
{
ProcessStartInfo start = new ProcessStartInfo();
start.FileName = "my/full/path/to/python.exe";
start.Arguments = string.Format("{0} {1}", cmd, args);
start.UseShellExecute = false;
start.RedirectStandardOutput = true;
using(Process process = Process.Start(start))
{
using(StreamReader reader = process.StandardOutput)
{
string result = reader.ReadToEnd();
Console.Write(result);
}
}
}
The reason it isn’t working is because you have UseShellExecute = false
.
If you don’t use the shell, you will have to supply the complete path to the python executable as FileName
, and build the Arguments
string to supply both your script and the file you want to read.
Also note, that you can’t RedirectStandardOutput
unless UseShellExecute = false
.
I’m not quite sure how the argument string should be formatted for python, but you will need something like this:
private void run_cmd(string cmd, string args)
{
ProcessStartInfo start = new ProcessStartInfo();
start.FileName = "my/full/path/to/python.exe";
start.Arguments = string.Format("{0} {1}", cmd, args);
start.UseShellExecute = false;
start.RedirectStandardOutput = true;
using(Process process = Process.Start(start))
{
using(StreamReader reader = process.StandardOutput)
{
string result = reader.ReadToEnd();
Console.Write(result);
}
}
}
回答 1
如果您愿意使用IronPython,则可以直接在C#中执行脚本:
using IronPython.Hosting;
using Microsoft.Scripting.Hosting;
private static void doPython()
{
ScriptEngine engine = Python.CreateEngine();
engine.ExecuteFile(@"test.py");
}
在此处获取IronPython。
If you’re willing to use IronPython, you can execute scripts directly in C#:
using IronPython.Hosting;
using Microsoft.Scripting.Hosting;
private static void doPython()
{
ScriptEngine engine = Python.CreateEngine();
engine.ExecuteFile(@"test.py");
}
Get IronPython here.
回答 2
从C执行Python脚本
创建一个C#项目并编写以下代码。
using System;
using System.Diagnostics;
using System.IO;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
run_cmd();
}
private void run_cmd()
{
string fileName = @"C:\sample_script.py";
Process p = new Process();
p.StartInfo = new ProcessStartInfo(@"C:\Python27\python.exe", fileName)
{
RedirectStandardOutput = true,
UseShellExecute = false,
CreateNoWindow = true
};
p.Start();
string output = p.StandardOutput.ReadToEnd();
p.WaitForExit();
Console.WriteLine(output);
Console.ReadLine();
}
}
}
Python sample_script
打印“ Python C#测试”
您将在C#控制台中看到“ Python C#测试”。
Execute Python script from C
Create a C# project and write the following code.
using System;
using System.Diagnostics;
using System.IO;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
run_cmd();
}
private void run_cmd()
{
string fileName = @"C:\sample_script.py";
Process p = new Process();
p.StartInfo = new ProcessStartInfo(@"C:\Python27\python.exe", fileName)
{
RedirectStandardOutput = true,
UseShellExecute = false,
CreateNoWindow = true
};
p.Start();
string output = p.StandardOutput.ReadToEnd();
p.WaitForExit();
Console.WriteLine(output);
Console.ReadLine();
}
}
}
Python sample_script
print "Python C# Test"
You will see the ‘Python C# Test’ in the console of C#.
回答 3
我遇到了同样的问题,道德大师的回答对我没有帮助。以下是基于先前答案的方法:
private void run_cmd(string cmd, string args)
{
ProcessStartInfo start = new ProcessStartInfo();
start.FileName = cmd;//cmd is full path to python.exe
start.Arguments = args;//args is path to .py file and any cmd line args
start.UseShellExecute = false;
start.RedirectStandardOutput = true;
using(Process process = Process.Start(start))
{
using(StreamReader reader = process.StandardOutput)
{
string result = reader.ReadToEnd();
Console.Write(result);
}
}
}
例如,如果要使用cmd行参数100执行test.py ,则cmd为,@C:/Python26/python.exe
而args为C://Python26//test.py 100
。请注意,.py文件的路径中没有@符号。
I ran into the same problem and Master Morality’s answer didn’t do it for me. The following, which is based on the previous answer, worked:
private void run_cmd(string cmd, string args)
{
ProcessStartInfo start = new ProcessStartInfo();
start.FileName = cmd;//cmd is full path to python.exe
start.Arguments = args;//args is path to .py file and any cmd line args
start.UseShellExecute = false;
start.RedirectStandardOutput = true;
using(Process process = Process.Start(start))
{
using(StreamReader reader = process.StandardOutput)
{
string result = reader.ReadToEnd();
Console.Write(result);
}
}
}
As an example, cmd would be @C:/Python26/python.exe
and args would be C://Python26//test.py 100
if you wanted to execute test.py with cmd line argument 100. Note that the path the .py file does not have the @ symbol.
回答 4
回答 5
设置WorkingDirectory或在Argument中指定python脚本的完整路径
ProcessStartInfo start = new ProcessStartInfo();
start.FileName = "C:\\Python27\\python.exe";
//start.WorkingDirectory = @"D:\script";
start.Arguments = string.Format("D:\\script\\test.py -a {0} -b {1} ", "some param", "some other param");
start.UseShellExecute = false;
start.RedirectStandardOutput = true;
using (Process process = Process.Start(start))
{
using (StreamReader reader = process.StandardOutput)
{
string result = reader.ReadToEnd();
Console.Write(result);
}
}
Set WorkingDirectory or specify the full path of the python script in the Argument
ProcessStartInfo start = new ProcessStartInfo();
start.FileName = "C:\\Python27\\python.exe";
//start.WorkingDirectory = @"D:\script";
start.Arguments = string.Format("D:\\script\\test.py -a {0} -b {1} ", "some param", "some other param");
start.UseShellExecute = false;
start.RedirectStandardOutput = true;
using (Process process = Process.Start(start))
{
using (StreamReader reader = process.StandardOutput)
{
string result = reader.ReadToEnd();
Console.Write(result);
}
}
回答 6
实际上,使用IronPython在Csharp(VS)和Python之间进行集成非常容易。并没有那么复杂…正如克里斯·邓纳维(Chris Dunaway)在回答部分中所述,我开始为自己的项目建立这种整合。N非常简单。只需按照这些步骤N,您将获得结果。
步骤1:打开VS并创建新的空ConsoleApp项目。
步骤2:转到工具-> NuGet软件包管理器->软件包管理器控制台。
步骤3:在此之后,在浏览器中打开此链接并复制NuGet命令。链接:https://www.nuget.org/packages/IronPython/2.7.9
步骤4:打开以上链接后,复制PM> Install-Package IronPython -Version 2.7.9命令并将其粘贴到VS的NuGet控制台中。它将安装支持包。
步骤5:这是我用来运行存储在我的Python.exe目录中的.py文件的代码。
using IronPython.Hosting;//for DLHE
using Microsoft.Scripting.Hosting;//provides scripting abilities comparable to batch files
using System;
using System.Diagnostics;
using System.IO;
using System.Net;
using System.Net.Sockets;
class Hi
{
private static void Main(string []args)
{
Process process = new Process(); //to make a process call
ScriptEngine engine = Python.CreateEngine(); //For Engine to initiate the script
engine.ExecuteFile(@"C:\Users\daulmalik\AppData\Local\Programs\Python\Python37\p1.py");//Path of my .py file that I would like to see running in console after running my .cs file from VS.//process.StandardInput.Flush();
process.StandardInput.Close();//to close
process.WaitForExit();//to hold the process i.e. cmd screen as output
}
}
步骤6:保存并执行代码
Actually its pretty easy to make integration between Csharp (VS) and Python with IronPython. It’s not that much complex… As Chris Dunaway already said in answer section I started to build this inegration for my own project. N its pretty simple.
Just follow these steps N you will get your results.
step 1 : Open VS and create new empty ConsoleApp project.
step 2 : Go to tools –> NuGet Package Manager –> Package Manager Console.
step 3 : After this open this link in your browser and copy the NuGet Command.
Link: https://www.nuget.org/packages/IronPython/2.7.9
step 4 : After opening the above link copy the PM>Install-Package IronPython -Version 2.7.9
command and paste it in NuGet Console in VS.
It will install the supportive packages.
step 5 : This is my code that I have used to run a .py file stored in my Python.exe
directory.
using IronPython.Hosting;//for DLHE
using Microsoft.Scripting.Hosting;//provides scripting abilities comparable to batch files
using System;
using System.Diagnostics;
using System.IO;
using System.Net;
using System.Net.Sockets;
class Hi
{
private static void Main(string []args)
{
Process process = new Process(); //to make a process call
ScriptEngine engine = Python.CreateEngine(); //For Engine to initiate the script
engine.ExecuteFile(@"C:\Users\daulmalik\AppData\Local\Programs\Python\Python37\p1.py");//Path of my .py file that I would like to see running in console after running my .cs file from VS.//process.StandardInput.Flush();
process.StandardInput.Close();//to close
process.WaitForExit();//to hold the process i.e. cmd screen as output
}
}
step 6 : save and execute the code
回答 7
我遇到问题stdin/stout
-当有效负载大小超过几千字节时,它挂起了。我不仅需要使用一些简短的参数来调用Python函数,还需要使用可能很大的自定义有效负载。
前一段时间,我编写了一个虚拟角色库,该库允许通过Redis在不同计算机上分发任务。为了调用Python代码,我添加了侦听来自Python的消息,对其进行处理并将结果返回给.NET的功能。
这是它如何工作的简要说明。
它也可以在一台机器上运行,但是需要一个Redis实例。Redis增加了一些可靠性保证-有效负载被存储,直到工作确认完成为止。如果工作人员死亡,则有效负载将返回到作业队列,然后由另一个工作人员重新处理。
I am having problems with stdin/stout
– when payload size exceeds several kilobytes it hangs. I need to call Python functions not only with some short arguments, but with a custom payload that could be big.
A while ago, I wrote a virtual actor library that allows to distribute task on different machines via Redis. To call Python code, I added functionality to listen for messages from Python, process them and return results back to .NET.
Here is a brief description of how it works.
It works on a single machine as well, but requires a Redis instance. Redis adds some reliability guarantees – payload is stored until a worked acknowledges completion. If a worked dies, the payload is returned to a job queue and then is reprocessed by another worker.