【问题标题】:How do I run a Python script from C#?如何从 C# 运行 Python 脚本?
【发布时间】:2017-05-18 07:21:39
【问题描述】:

这样的问题以前也有不同程度的问过,但是感觉回答的不够简洁,所以又问了一遍。

我想在 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 位置传递为cmd 并将filename 位置传递为args 时,它不起作用。有人告诉我应该将python.exe 传递为cmd,然后将code.py filename 传递为args。

我已经找了一段时间了,只能找到建议使用 IronPython 之类的人。但是必须有一种方法可以从 C# 调用 Python 脚本。

一些澄清:

我需要从 C# 运行它,我需要捕获输出,我不能使用 IronPython 或其他任何东西。无论你有什么技巧都可以。

P.S.:我实际运行的 Python 代码比这复杂得多,它会返回我在 C# 中需要的输出,而 C# 代码会不断调用 Python 代码。

假装这是我的代码:

    private void get_vals()
    {
        for (int i = 0; i < 100; i++)
        {
            run_cmd("code.py", i);
        }
    }

【问题讨论】:

  • C# 代码是否必须调用 Python 脚本,或者如果(如您最后所说)您只需调用然后运行脚本的 python 解释器就可以了吗?
  • 你可以使用 IronPython 吗?
  • @GeraldVersluis 没关系,我只需要能够通过 c# 运行它并捕获输出。

标签: c# python .net ironpython python.net


【解决方案1】:

它不工作的原因是因为你有UseShellExecute = false。

如果您不使用 shell,则必须将 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);
         }
     }
}

【讨论】:

  • 我希望能够将输出带到我的程序中以供以后使用。所以我需要将 shellexecute 设置为 false。你是说如果我将c:\python26\python.exe 传递为cmd 然后将c:\temp\code.py c:\temp\testfile.txt 传递为args 它应该可以工作吗?
  • 我更新了一个简单的例子,当我用节点做类似的事情时遇到了同样的问题
  • 好的,它现在对我有用。问题是您需要非常仔细地格式化字符串。任何路径都需要"PATH",即使没有空格...奇怪...
  • 如果 Python 安装程序被告知将 Python 目录添加到环境变量 PATH(系统或用户特定)中,则无需提供路径即可工作。
  • @MasterMorality ,python脚本执行得很好,但是如果python中有一些模块依赖,我们该如何解决呢?
【解决方案2】:

如果你愿意使用 IronPython,你可以直接在 C# 中执行脚本:

using IronPython.Hosting;
using Microsoft.Scripting.Hosting;

private static void doPython()
{
    ScriptEngine engine = Python.CreateEngine();
    engine.ExecuteFile(@"test.py");
}

Get IronPython here.

【讨论】:

  • 向我解释一下,我可以在不下载任何东西的情况下这样做吗? c# 准备好这个插件了吗?还有——我可以用这个运行外部脚本吗?
  • 请注意 IronPython 和 Python 并不完全相同。只是为了记录......
  • IronPython 似乎不支持与 Python 3.6.x 相同的语言特性集。因此,如果您不使用任何这些语言功能,IronPython 只是一种选择。不过,这绝对值得一试。
  • 我们可以用ironpython 2.7版本运行python 3.6吗?我试过了,但它没有导入任何 python 库。我收到unexpected token from 请帮忙
  • 不,IronPython 仅与 Python 2.7 兼容。 IronPython3 正在开发中。
【解决方案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 文件的路径没有 @ 符号。

【讨论】:

  • 有人可以评论为什么这是-1。它有什么问题。
  • 这与上面的答案完全相同,只是您从参数中分配 FileName 。但最后start 具有相同的值
【解决方案4】:

从 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 示例脚本

打印“Python C# 测试”

您将在 C# 的控制台中看到 'Python C# Test'。

【讨论】:

  • 我在 Windows 文件夹中有一个 python 脚本文件,例如C:\Users\Documents\Visual Studio 2019。由于文件夹路径中的空格,它被视为args的分隔符,所以我得到fileName找不到。有没有办法逃离这个空间?
  • 我有一个利用 pip 包的脚本。这仍然有效吗?我只是将包放在与 python.exe 相同的文件夹中吗?
【解决方案5】:

我遇到了stdin/stout 的问题 - 当有效负载大小超过几千字节时,它会挂起。我不仅需要使用一些短参数调用 Python 函数,还需要使用可能很大的自定义有效负载。

前段时间,我写了一个虚拟actor库,允许通过Redis在不同的机器上分发任务。为了调用 Python 代码,我添加了侦听来自 Python 的消息、处理它们并将结果返回给 .NET 的功能。 Here is a brief description of how it works.

它也可以在单台机器上工作,但需要一个 Redis 实例。 Redis 增加了一些可靠性保证 - 有效负载被存储,直到工作确认完成。如果一个工作的人死亡,有效载荷将返回到一个工作队列,然后由另一个工作人员重新处理。

【讨论】:

  • 为什么不直接使用 in-out 文件?而不是让管道处理所有这些工作。
  • @InbarRose 我已经有了 .NET 系统,所以添加 Python 处理非常容易,而且我仍然有分布和可靠性 - 例如。我可以从 Windows 机器发布有效负载并从 Linux 机器处理它 - 在这种情况下文件将无法工作。
  • @InbarRose 当有效负载非常大时,我可以在同一台机器上传递文件名或在 AWS 上传递 S3 引用等...
【解决方案6】:

设置 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);
    }
}

【讨论】:

    【解决方案7】:

    实际上,使用 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
    }
    } 
    

    第六步:保存并执行代码

    【讨论】:

    • 作为开发人员,我不会选择解决方案,因为它“易于”实施。我选择一个可以完成这项工作的人。 IronPython 仅移植到 python 2.7 并且在 python 3 上的工作现在已经进行了几年,但看不到尽头。希望您的 python 代码版本正确。
    • 截至 2020 年 4 月 27 日:github.com/IronLanguages/ironpython2/releases/tag/ipy-2.7.10,但仍然不是 python 3。
    【解决方案8】:

    简单,您将需要铁蟒,但我使用的一种方法是:

    using IronPython.Hosting;
    
      var engine = Python.CreateEngine();
    
      engine.ExecuteFile("") //put the directory of the program in the quote marks
    

    【讨论】:

      猜你喜欢
      • 2016-02-05
      • 1970-01-01
      • 2021-01-27
      • 1970-01-01
      • 2014-11-04
      相关资源
      最近更新 更多