在 Windows 上,Python 没有内置的守护进程(daemon)模块。但是你可以使用 pywin32 模块来实现类似的功能。先安装 pywin32 模块,然后使用 pywin32 模块调用 windows 服务 API 创建一个后台服务。
最终效果是在 services.msc 中会多出一个自定义的服务:
在给出示例代码前要先安装 pywin32 模块:
C:> pip install pywin32
同时我们还会用到 psutil 获取进程 ID,需要安装 psutil 模块:
C:> pip install psutil
以下代码实现了一个后台进程,它会先将进程的PID写入到指定的文件中,然后启动一个死循环,每5秒打印一条消息代表进程还存活着。
#!python3
# Filename: pyservices.py
import win32serviceutil
import win32service
import win32event
import servicemanager
import socket
import sys
import time
import psutil
def write_process_id_to_file(file_path):
pid = str(psutil.Process().pid)
with open(file_path, 'w') as file:
file.write(pid)
# 进程ID
process_id_file_path = r"d:MyPythonService.pid"
class MyService(win32serviceutil.ServiceFramework):
_svc_name_ = "MyPythonService"
_svc_display_name_ = "My Python Service"
def __init__(self, args):
win32serviceutil.ServiceFramework.__init__(self, args)
self.hWaitStop = win32event.CreateEvent(None, 0, 0, None)
socket.setdefaulttimeout(60)
self.is_alive = True
def SvcStop(self):
self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)
win32event.SetEvent(self.hWaitStop)
self.is_alive = False
def SvcDoRun(self):
servicemanager.LogMsg(servicemanager.EVENTLOG_INFORMATION_TYPE,
servicemanager.PYS_SERVICE_STARTED,
(self._svc_name_, ''))
self.main()
def main(self):
write_process_id_to_file(process_id_file_path)
while self.is_alive:
# 在这里编写你的守护进程主要逻辑
print("Daemon is running...")
time.sleep(5)
if __name__ == '__main__':
if len(sys.argv) == 1:
servicemanager.Initialize()
servicemanager.PrepareToHostSingle(MyService)
servicemanager.StartServiceCtrlDispatcher()
else:
win32serviceutil.HandleCommandLine(MyService)
以管理员身份运行 cmd,在命令行安装当前服务:
d:> python pyservices.py install
Installing service MyPythonService
copying host exe 'C:UsersAdministratorAppDataLocalProgramsPythonPython311Libsite-packageswin32pythonservice.exe' -> 'C:UsersAdministratorAppDataLocalProgramsPythonPython311pythonservice.exe'
copying helper dll 'C:UsersAdministratorAppDataLocalProgramsPythonPython311Libsite-packagespywin32_system32pywintypes311.dll' -> 'C:UsersAdministratorAppDataLocalProgramsPythonPython311pywintypes311.dll'
Service installed
安装完后即可在 services.msc 中查看到 MyPythonService 已经注册到系统服务中了。
此时可以在服务面板中对服务进行启停,也可以在命令行中对注册的服务进行启停:
C:> net stop MyPythonService
My Python Service 服务正在停止..
My Python Service 服务已成功停止。
C:> net start MyPythonService
My Python Service 服务正在启动 .
My Python Service 服务已经启动成功。
同时,我们也可以在刚才的脚本执行位置对注册的服务进行启停:
d:> python pyservices.py start
Starting service MyPythonService
d:> python pyservices.py stop
Stopping service MyPythonService
d:> python pyservices.py restart
Restarting service MyPythonService
除了启停服务之外,我们还能能 debug 方式运行服务。当以 debug 方式运行时,服务不会以后台方式运行,并且可以通过 ctrl+c 结束程序:
d:> python pyservices.py debug
Debugging service MyPythonService - press Ctrl+C to stop.
Info 0x40001002 - The MyPythonService service has started.
Daemon is running...
Daemon is running...
Daemon is running...
当代码有更新时可以通过 update 命令更新服务:
d:> python pyservices.py update
Changing service configuration
copying host exe 'C:UsersAdministratorAppDataLocalProgramsPythonPython311Libsite-packageswin32pythonservice.exe' -> 'C:UsersAdministratorAppDataLocalProgramsPythonPython311pythonservice.exe'
Service updated
当不再需要运行此服务时,可以注销掉服务:
d:> python pyservices.py remove
Removing service MyPythonService
Service removed
全文完。
如果转发本文,文末务必注明:“转自微信公众号:生有可恋”。
原文始发于微信公众号(生有可恋):使用 python 创建 windows 服务
免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论