How do I run a Python script from C#?

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

Solution 1:

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

Solution 2:

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.

Solution 3:

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#.