0

I am trying to run python script in c# with process.

private void RunScript()
{
    ProcessStartInfo processStartInfo = new ProcessStartInfo("python.exe", "c:\\path\\to\\script\\PullRequest.py");
    processStartInfo.CreateNoWindow = true;
    processStartInfo.UseShellExecute = false;
    processStartInfo.RedirectStandardError = true;
    processStartInfo.RedirectStandardOutput = true;

    Process process = new Process();
    process.StartInfo = processStartInfo;
    process.Start();

    m_Output = process.StandardOutput.ReadToEnd();
    m_Error = process.StandardError.ReadToEnd();

    process.WaitForExit();
}

However I got the following error :

No module named requests

How can i run this script from my virtual environment, where the requests module is installed ?

1
  • Probably by specifying a path to the virtual environment python executable instead of just python.exe. Commented Mar 7, 2022 at 12:13

1 Answer 1

2

You have to first activate your virtual environment, you can simply specify the path to the pip and python executables in the .venv/bin directory.

Another way is to simply activate the virtual environment so that the commands are executed in the venv. I am currently running it like this in a Linux container:

const string cmd = "bash";
const string args = "";
const string activateVenv = "source .venv/bin/activate";
var commandsToExecute = new List<string>(){
    "pip install -r requirements.txt",
    "python /path/to/script arg1 arg2 arg3"
};

var startInfo = new ProcessStartInfo
{
    RedirectStandardOutput = true,
    RedirectStandardInput = true,
    RedirectStandardError = true,
    UseShellExecute = false,
    CreateNoWindow = true,
    Arguments = args,
    FileName = cmd,
    WorkingDirectory = workingDirectory
};

var process = Process.Start(startInfo);
if (process == null)
    throw new Exception("Could not start process");

using var sw = process.StandardInput;
if (sw.BaseStream.CanWrite)
{
    sw.WriteLine(activateVenv);
    foreach (var command in commandsToExecute)
    {
        sw.WriteLine(command);
    }
    sw.Flush();
    sw.Close();
}

var sb = new StringBuilder();
while (!process.HasExited)
    sb.Append(process.StandardOutput.ReadToEnd());

var error = process.StandardError.ReadToEnd();
if (!string.IsNullOrEmpty(error))
    throw new Exception($"Something went wrong: \n{error}");

return sb.ToString();

This enables me to simply pass the commands as a list of strings, e.g. first I'm running pip install -r requirements.txt then python /path/to/script arg1 arg2 arg3, thus not having to deal with paths to the pip and python executables in the venv directory respectively.

If you are using it on Windows you would have to change the way it is invoked to use powershell and the Activate.ps1 script in the venv directory. There are probably a few things that could be optimized but this is how I got it working. If I find improvements I'll update the answer.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.