如何将带无限循环的Python脚本部署为Windows服务并解决启动超时?
将含无限循环的Python脚本部署为Windows服务的解决方案
一、通过pywin32实现标准Windows服务接口
Windows服务需要与系统服务管理器交互,报告状态并响应启停信号,直接运行普通脚本会因无法反馈启动状态导致超时。以下是改造步骤:
1. 安装依赖
在你的虚拟环境中安装pywin32库:
E:\Python_Venv\env310_1\Scripts\pip.exe install pywin32
2. 改造Python脚本
将原脚本修改为符合Windows服务规范的版本,继承win32serviceutil.ServiceFramework并实现服务生命周期方法:
import threading import time import win32serviceutil import win32service import win32event import sys class NmsCoreService(win32serviceutil.ServiceFramework): # 服务名称、显示名称、描述,需与PowerShell脚本中定义的一致 _svc_name_ = "nmsCore" _svc_display_name_ = "NMS CORE SERVICE" _svc_description_ = "This is a sample service." def __init__(self, args): win32serviceutil.ServiceFramework.__init__(self, args) # 创建停止事件,用于监听服务停止信号 self.hWaitStop = win32event.CreateEvent(None, 0, 0, None) self.running = True self.business_thread = None def SvcStop(self): # 报告服务即将停止 self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING) # 标记业务线程停止 self.running = False # 触发停止事件 win32event.SetEvent(self.hWaitStop) # 等待业务线程结束(可选,根据业务逻辑调整) if self.business_thread is not None: self.business_thread.join() # 报告服务已停止 self.ReportServiceStatus(win32service.SERVICE_STOPPED) def SvcDoRun(self): # 报告服务已启动 self.ReportServiceStatus(win32service.SERVICE_RUNNING) # 启动业务线程 self.business_thread = threading.Thread(target=self.business_logic) self.business_thread.start() # 等待停止信号 win32event.WaitForSingleObject(self.hWaitStop, win32event.INFINITE) def business_logic(self): # 你的核心业务逻辑,原无限循环代码 while self.running: time.sleep(1) # 使用with语句确保文件正确关闭,改为追加模式避免覆盖日志 with open(r'E:\test.log', 'a', encoding='utf-8') as f: f.write('hello\n') if __name__ == '__main__': # 处理服务命令(install/start/stop/delete等) win32serviceutil.HandleCommandLine(NmsCoreService)
3. 修改PowerShell管理脚本
由于pywin32已内置服务注册逻辑,可简化PowerShell脚本,直接调用Python脚本的服务命令:
param( [string]$arg1 ) # 定义路径 $pythonExecutable = "E:\Python_Venv\env310_1\Scripts\python.exe" $scriptPath = "E:\Working\nmscore\v1\pycode\nmscore_service.py" switch ($arg1) { "install" { & $pythonExecutable $scriptPath install Write-Output "Service installed." } "start" { & $pythonExecutable $scriptPath start Write-Output "Service started." } "stop" { & $pythonExecutable $scriptPath stop Write-Output "Service stopped." } "delete" { & $pythonExecutable $scriptPath remove Write-Output "Service deleted." } "restart" { & $pythonExecutable $scriptPath stop Start-Sleep -Seconds 2 & $pythonExecutable $scriptPath start Write-Output "Service restarted." } "reinstall" { & $pythonExecutable $scriptPath remove Start-Sleep -Seconds 2 & $pythonExecutable $scriptPath install Write-Output "Service re-installed." } default { Write-Output "Invalid command. Use: install/start/stop/delete/restart/reinstall" } }
二、无需修改代码:使用NSSM工具包装服务
如果你不想修改Python代码,可以使用**NSSM(Non-Sucking Service Manager)**将任意可执行程序包装为Windows服务,它会自动处理服务状态报告和启停逻辑:
1. 下载并配置NSSM
下载对应系统版本的NSSM压缩包,解压后将nssm.exe放到系统PATH目录(如C:\Windows\System32)或指定路径。
2. 安装服务
打开管理员PowerShell,执行以下命令:
nssm install nmsCore
在弹出的配置窗口中:
- Path:选择你的Python虚拟环境可执行路径
E:\Python_Venv\env310_1\Scripts\python.exe - Arguments:填写你的脚本路径
E:\Working\nmscore\v1\pycode\nmscore_service.py - Working Directory:可选,填写脚本所在目录
E:\Working\nmscore\v1\pycode - 切换到Details标签,设置服务显示名称和描述,与之前的配置一致。
- 点击Install service完成安装。
3. 使用PowerShell管理服务
你可以继续使用原PowerShell脚本管理服务,因为NSSM注册的服务与系统原生服务完全兼容,Start-Service、Stop-Service等命令均可正常使用。
三、优化建议
- 日志管理:替换直接写文件的方式,使用Python内置的
logging模块,支持日志级别、滚动日志等功能,便于排查问题。 - 优雅停止:对于复杂业务逻辑,可使用
threading.Event代替布尔标志,更安全地控制线程停止。 - 权限配置:确保服务运行账户有足够权限访问脚本、日志文件及其他资源,建议使用专用服务账户而非管理员账户。
- 错误处理:在业务逻辑中添加异常捕获,避免单个错误导致服务崩溃。
内容的提问来源于stack exchange,提问作者CoderButBeginner
相关产品推荐
相关产品推荐

