如何在C#/.NET Core中通过命令行调用带参数的Python脚本
现有写法的错误原因
1. IronPython(ScriptRuntime)写法错误
- sys.argv的格式不符合Python规范:
sys.argv第一个元素应为脚本自身的路径,你错误的将python + 脚本路径 + 第一个参数拼成字符串作为第一个元素,后续还把多个参数合并成单个字符串塞到列表里,完全不符合参数解析的要求 - 参数拼接缺少空格:比如
-input_path和后面的路径直接拼接,会变成-input_pathC:\xxx,脚本的参数解析器根本识别不了这个参数名 - 额外问题:IronPython对CPython的第三方库兼容度很低,如果你的run_edr.py依赖了第三方包,这种写法本身就不可能运行成功
2. 系统进程(Process)写法错误
- 调用cmd.exe时缺少
/c参数:cmd.exe执行传入的命令必须加/c前缀,否则不会执行后续的命令,直接静默退出 - 路径未加双引号包裹:如果路径包含空格会直接解析错误,就算当前路径没空格也建议统一加双引号适配所有情况
- 未设置工作目录:你没有指定进程的工作目录为脚本所在文件夹,系统找不到
run_edr.py文件 - Windows命令行不识别单引号:你给site_name等参数的值用了单引号,Windows下只有双引号会被当做参数包裹符,单引号会被当成参数值的一部分,导致参数解析错误
正确实现(推荐用系统进程调用,兼容性最好)
using System.Diagnostics; // 先配置各个路径,建议统一存到变量里方便修改 string pythonPath = @"python.exe"; // 可以换成你本地python的绝对路径,比如@"C:\Python39\python.exe",避免环境变量问题 string scriptDir = @"C:\Users\aslamm5165\Downloads\EDRCODE_ArgParser"; string scriptPath = Path.Combine(scriptDir, "run_edr.py"); string inputPath = @"C:\Users\aslamm5165\Downloads\EDRCODE_ArgParser\files\EDR"; string outputPath = @"C:\Users\aslamm5165\Downloads\test"; ProcessStartInfo startInfo = new ProcessStartInfo() { FileName = pythonPath, // 所有参数值都用双引号包裹 Arguments = $"\"{scriptPath}\" -input_path \"{inputPath}\" -output_path \"{outputPath}\" -site_name \"a\" -site_address \"b\" -site_city \"c\" -site_county \"d\" -site_state \"e\" -site_type \"1\"", WorkingDirectory = scriptDir, // 必须设置工作目录为脚本所在文件夹 UseShellExecute = false, CreateNoWindow = true, // 如果需要捕获脚本输出可以打开下面两个配置 // RedirectStandardOutput = true, // RedirectStandardError = true }; using (Process process = Process.Start(startInfo)) { process.WaitForExit(); // 等待脚本执行完成,不需要的话可以去掉 // 如果需要排查执行问题可以读输出信息 // string output = process.StandardOutput.ReadToEnd(); // string error = process.StandardError.ReadToEnd(); // int exitCode = process.ExitCode; // 可用来判断脚本是否执行成功,一般0代表执行成功 }
如果你一定要用IronPython的方式,修正后的代码如下(仅适用于脚本没有依赖第三方CPython库的场景):
ScriptRuntimeSetup setup = Python.CreateRuntimeSetup(null); ScriptRuntime runtime = new ScriptRuntime(setup); ScriptEngine engine = Python.GetEngine(runtime); string scriptPath = @"C:\Users\aslamm5165\Downloads\EDRCODE_ArgParser\run_edr.py"; ScriptSource source = engine.CreateScriptSourceFromFile(scriptPath); ScriptScope scope = engine.CreateScope(); List<string> argv = new List<string>(); // 第一个元素是脚本自身路径 argv.Add(scriptPath); // 每个参数名和参数值都要单独作为一个元素 argv.Add("-input_path"); argv.Add(@"C:\Users\aslamm5165\Downloads\EDRCODE_ArgParser\files\EDR"); argv.Add("-output_path"); argv.Add(@"C:\Users\aslamm5165\Downloads\test"); argv.Add("-site_name"); argv.Add("a"); argv.Add("-site_address"); argv.Add("b"); argv.Add("-site_city"); argv.Add("c"); argv.Add("-site_county"); argv.Add("d"); argv.Add("-site_state"); argv.Add("e"); argv.Add("-site_type"); argv.Add("1"); engine.GetSysModule().SetVariable("argv", argv); source.Execute(scope);
内容的提问来源于stack exchange,提问作者Md Aslam
相关产品推荐
相关产品推荐

