[英]C# run python script from virtual environment
I am trying to run python script in c# with process.我正在尝试使用进程在 c# 中运行 python 脚本。
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?我如何从安装了请求模块的虚拟环境中运行此脚本?
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.您必须首先激活您的虚拟环境,您可以简单地在
.venv/bin
目录中指定pip
和python
可执行文件的路径。
Another way is to simply activate the virtual environment so that the commands are executed in the venv.另一种方法是简单地激活虚拟环境,以便在 venv 中执行命令。 I am currently running it like this in a Linux container:
我目前在 Linux 容器中像这样运行它:
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, eg 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.这使我能够简单地将命令作为字符串列表传递,例如,首先我正在运行
pip install -r requirements.txt
然后python /path/to/script arg1 arg2 arg3
,因此不必处理到 pip 和venv目录下分别有python个可执行文件。
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.如果您在 Windows 上使用它,则必须更改它的调用方式以使用 powershell 和 venv 目录中的
Activate.ps1
脚本。 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.
如果我发现改进,我会更新答案。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.