千家信息网

利用C#守护Python进程的方法是什么

发表于:2026-11-04 作者:千家信息网编辑
千家信息网最后更新 2026年11月04日,利用C#守护Python进程的方法是什么,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。背景目前我主要负责的一个项目是一个 C/S 架
千家信息网最后更新 2026年11月04日利用C#守护Python进程的方法是什么

利用C#守护Python进程的方法是什么,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。

背景

目前我主要负责的一个项目是一个 C/S 架构的客户端开发,前端主要是通过 WPF 相关技术来实现,后端是通过 Python 来实现,前后端的数据通信则是通过 MQ 的方式来进行处理。由于 Python 进程是需要依赖客户端进程来运行,为了保证后端业务进程的稳定性,就需要通过一个 守护进程 来守护 Python 进程,防止其由于未知原因而出现进程退出的情况。这里简单记录一下我的一种实现方式。

实现#

对于我们的系统而言,我们的 Python 进程只允许存在一个,因此,对应的服务类型要采用单例模式,这一部分代码相对简单,就直接贴出来了,示例代码如下所示:

public partial class PythonService{ private static readonly object _locker = new object(); private static PythonService _instance; public static PythonService Current { get { if (_instance == null) { lock (_locker) { if (_instance == null) { _instance = new PythonService(); } } } return _instance; } } private PythonService() { }}

创建独立进程#

由于后端的 Python 代码运行需要安装一些第三方的扩展库,所以为了方便,我们采用的方式是总结将 python 安装文件及扩展包和他们的代码一并打包到我们的项目目录中,然后创建一个 Python 进程,在该进程中通过设置环境变量的方式来为 Python 进程进行一些环境配置。示例代码如下所示:

public partial class PythonService{ private string _workPath => Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "scripts"); private string _pythonPath => Path.Combine(_workPath, "python27"); private bool isRunning = false; private int taskPID = -1; public void Start() { taskPID = CreateProcess(); isRunning = taskPID != -1; var msg = isRunning ? "服务启动成功..." : "服务启动失败..."; Trace.WriteLine(msg); } public void Stop() { KillProcessAndChildren(taskPID); isRunning = false; taskPID = -1; } private int CreateProcess() { KillProcessAndChildren(taskPID); int pid = -1; var psi = new ProcessStartInfo(Path.Combine(_pythonPath, "python.exe")) { UseShellExecute = false, WorkingDirectory = _workPath, ErrorDialog = false }; psi.CreateNoWindow = true; var path = psi.EnvironmentVariables["PATH"]; if (path != null) { var array = path.Split(new[] { ';' }).Where(p => !p.ToLower().Contains("python")).ToList(); array.AddRange(new[] { _pythonPath, Path.Combine(_pythonPath, "Scripts"), _workPath }); psi.EnvironmentVariables["PATH"] = string.Join(";", array); } var ps = new Process { StartInfo = psi }; if (ps.Start()) { pid = ps.Id; } return pid; } private static void KillProcessAndChildren(int pid) { // Cannot close 'system idle process'. if (pid <= 0) { return; } ManagementObjectSearcher searcher = new ManagementObjectSearcher("Select * From Win32_Process Where ParentProcessID=" + pid); ManagementObjectCollection moc = searcher.Get(); foreach (ManagementObject mo in moc) { KillProcessAndChildren(Convert.ToInt32(mo["ProcessID"])); } try { Process proc = Process.GetProcessById(pid); proc.Kill(); } catch (ArgumentException) { // Process already exited. } catch (Win32Exception) { // Access denied } }}

这里有一点需要注意一下,建议使用 PID 来标识我们的 Python 进程,因为如果你使用进程实例或其它方式来对当前运行的进程设置一个引用,当该进程出现一些未知退出,这个时候你通过哪个引用来进行相关操作是会出问题的。

创建守护进程#

上面我们的通过记录当前正在运行的进程的 PID 来标识我们的进程,那对应守护进程,我们就可以通过进程列表查询的方式来进行创建,在轮询的过程中,如果未找到对应 PID 的进程则表明该进程已经退出,需要重新创建该进程,否则就不执行任何操作,示例代码如下所示:

public partial class PythonService{ private CancellationTokenSource cts; private void StartWatch(CancellationToken token) { Task.Factory.StartNew(() => { while (!token.IsCancellationRequested) { var has = Process.GetProcesses().Any(p => p.Id == taskPID); Trace.WriteLine($"MQ状态:{DateTime.Now}-{has}"); if (!has) { taskPID = CreateProcess(_reqhost, _subhost, _debug); isRunning = taskPID > 0; var msg = isRunning ? "MQ重启成功" : "MQ重启失败,等待下次重启"; Trace.WriteLine($"MQ状态:{DateTime.Now}-{msg}"); } Thread.Sleep(2000); } }, token); }}

这里我使用的是 Thread.Sleep(2000) 方式来继续线程等待,你也可以使用 await Task.Delay(2000,token),但是使用这种方式在发送取消请求时会产生一个 TaskCanceledException 的异常。所以为了不产生不必要的异常信息,我采用第一种解决方案。

接着,完善我们的 Start 和 Stop 方法,示例代码如下所示:

public void Start(){ taskPID = CreateProcess(); isRunning = taskPID != -1; if (isRunning) { cts = new CancellationTokenSource(); StartWatch(cts.Token); } var msg = isRunning ? "服务启动成功..." : "服务启动失败..."; Trace.WriteLine(msg);}public void Stop(){ cts?.Cancel(false); cts?.Dispose(); KillProcessAndChildren(taskPID); taskPID = -1; isRunning = false;}

最后,上层调用就相对简单一下,直接调用 Start 方法和 Stop 方法即可。

总结

在我们的实际项目代码中,PythonService 的代码要比上面的代码稍微复杂一些,我们内部还添加了一个 MQ 的 消息队列。所以为了演示方便,我这里只列出了和本文相关的核心代码,在具体的使用过程中,可以依据本文提供的一种实现方法来进行加工处理。

关于利用C#守护Python进程的方法是什么问题的解答就分享到这里了,希望以上内容可以对大家有一定的帮助,如果你还有很多疑惑没有解开,可以关注行业资讯频道了解更多相关知识。

进程 代码 方式 方法 服务 示例 问题 运行 成功 项目 C# 客户 客户端 更多 标识 状态 环境 端的 过程 处理 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 互联网科技工作委员会副主任毛军 盈实互联网科技 金诺互联网科技 科技互联网技术 互联网科技开发公司 科技与互联网发展 互联网科技公司官网 互联网科技公司招聘 创业天下互联网科技有限公司 重庆互联网医院沙龙医盟信息科技 荆州市昕露互联网络科技有限公司 崇明区互联网教育科技售后服务 辽宁互联网新科技 消费医药和互联网科技 威龙国际互联网科技公司 半导体是互联网高科技吗 福建互联网展示科技馆设计 米泉互联网科技专业怎么样 青岛易易互联网科技 宁波允成互联网科技有限公司 互联网科技有限公司 互联网科技卖菜 华中科技有哪些互联网大佬 中国的互联网科技企业的崛起 顶级互联网科技成果有哪些 南山科技园互联网公司有哪些 互联网校园科技培训 互联网科技和法律行业 互联网科技包装股份有限公司上市 如何强化互联网金融科技
0