Python
C#
scripting
interoperability
programming

How do I run a Python script from C?

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

Introduction

Running Python from C# is straightforward when you treat Python as a separate executable, but some projects need tighter integration. For example, a long-running desktop app might want to call Python functions repeatedly without spawning a new process for each operation.

Process-Based Execution First

Even if you eventually embed Python, start by understanding the process model. It is easier to debug, easier to deploy in small tools, and often fast enough for scheduled jobs or one-shot tasks.

csharp
1using System;
2using System.Diagnostics;
3
4class Program
5{
6    static int Main()
7    {
8        var psi = new ProcessStartInfo
9        {
10            FileName = "python",
11            Arguments = "worker.py 5 7",
12            RedirectStandardOutput = true,
13            RedirectStandardError = true,
14            UseShellExecute = false,
15            CreateNoWindow = true
16        };
17
18        using var process = Process.Start(psi);
19        if (process is null)
20        {
21            Console.Error.WriteLine("Failed to start Python.");
22            return 1;
23        }
24
25        string stdout = process.StandardOutput.ReadToEnd();
26        string stderr = process.StandardError.ReadToEnd();
27        process.WaitForExit();
28
29        Console.WriteLine(stdout.Trim());
30        if (process.ExitCode != 0)
31        {
32            Console.Error.WriteLine(stderr);
33        }
34
35        return process.ExitCode;
36    }
37}

Python can stay simple:

python
1# worker.py
2import sys
3
4x = int(sys.argv[1])
5y = int(sys.argv[2])
6print(x + y)

This approach is excellent for utilities, background jobs, and wrappers around existing scripts.

Calling Python In-Process with pythonnet

If process startup cost becomes a bottleneck, pythonnet lets C# load the Python runtime and call Python code in the same process. That removes the need for command line parsing and text-based data exchange, but it introduces runtime configuration concerns.

A minimal example looks like this:

csharp
1using Python.Runtime;
2
3class Program
4{
5    static void Main()
6    {
7        PythonEngine.Initialize();
8
9        using (Py.GIL())
10        {
11            dynamic math = Py.Import("math");
12            dynamic result = math.sqrt(81);
13            Console.WriteLine((double)result);
14        }
15
16        PythonEngine.Shutdown();
17    }
18}

The Py.GIL() block is critical because Python code must run while holding the Global Interpreter Lock. If your application is multithreaded, that detail matters immediately.

Tradeoffs Between the Two Approaches

Process execution has stronger isolation. If the Python script crashes, it normally does not take down the host process. It also makes dependency management clearer because the Python environment is explicit.

In-process execution has lower call overhead and richer interoperability. You can import modules, call functions, and work with objects directly. The cost is a more sensitive runtime setup, tighter version coupling, and more care around threading.

As a rule, use a child process when the Python code behaves like a tool. Use pythonnet when Python behaves like a library and performance justifies the extra complexity.

Deployment Considerations

Whichever path you choose, pin the Python version. Cross-language integration breaks most often because development and production use different interpreters or different package sets.

For process-based execution, keep the interpreter path configurable and log it at startup. For embedded execution, verify that the installed Python version matches the pythonnet package and the native runtime files available on the machine.

It is also worth thinking about failure reporting. A process exit code is easy to inspect. An embedded call can fail with initialization errors, import errors, or native loading issues that are harder to diagnose unless you capture detailed logs.

Common Pitfalls

One common mistake is assuming a process-based integration is always slow. If your script runs for several seconds, the process startup overhead may be negligible. Measure before moving to a more complex embedding solution.

Another issue is forgetting the GIL when using pythonnet. Code may appear to work in a trivial example and then behave unpredictably once multiple threads are involved.

A third mistake is mixing package environments. The Python interpreter your system launches may not be the same one where your dependencies were installed. That usually shows up as ModuleNotFoundError even though the package seems to exist locally.

Summary

  • Use ProcessStartInfo when Python acts like an external tool.
  • Use pythonnet when you need repeated in-process calls to Python code.
  • Process execution is simpler and more isolated.
  • Embedded execution reduces call overhead but requires careful runtime management.
  • Interpreter versioning and environment consistency are essential in both models.

Related reading
Course
Intermediate
27 lessons
14 hours
OOD Fundamentals

Master object-oriented design from first principles, SOLID, design patterns, and classic interview problems with hands-on coding.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

All Rights Reserved.