首先让我们开始安装Python for Windows扩展:
c:test>pip install pywin32
完成后,让我们编写该基类,您的Windows服务将是该基类的子类。
'''
SMWinservice
by Davide Mastromatteo
Base class to create winservice in Python
-----------------------------------------
Instructions:
1. Just create a new class that inherits from this base class
2. Define into the new class the variables
_svc_name_ = "nameOfWinservice"
_svc_display_name_ = "name of the Winservice that will be displayed in scm"
_svc_description_ = "description of the Winservice that will be displayed in scm"
3. Override the three main methods:
def start(self) : if you need to do something at the service initialization.
A good idea is to put here the inizialization of the running condition
def stop(self) : if you need to do something just before the service is stopped.
A good idea is to put here the invalidation of the running condition
def main(self) : your actual run loop. Just create a loop based on your running condition
4. Define the entry point of your module calling the method "parse_command_line" of the new class
5. Enjoy
'''
import socket
import win32serviceutil
import servicemanager
import win32event
import win32service
class SMWinservice(win32serviceutil.ServiceFramework):
'''Base class to create winservice in Python'''
_svc_name_ = 'pythonService'
_svc_display_name_ = 'Python Service'
_svc_description_ = 'Python Service Description'
@classmethod
def parse_command_line(cls):
'''
ClassMethod to parse the command line
'''
win32serviceutil.HandleCommandLine(cls)
def __init__(self, args):
'''
Constructor of the winservice
'''
win32serviceutil.ServiceFramework.__init__(self, args)
self.hWaitStop = win32event.CreateEvent(None, 0, 0, None)
socket.setdefaulttimeout(60)
def SvcStop(self):
'''
Called when the service is asked to stop
'''
self.stop()
self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)
win32event.SetEvent(self.hWaitStop)
def SvcDoRun(self):
'''
Called when the service is asked to start
'''
self.start()
servicemanager.LogMsg(servicemanager.EVENTLOG_INFORMATION_TYPE,
servicemanager.PYS_SERVICE_STARTED,
(self._svc_name_, ''))
self.main()
def start(self):
'''
Override to add logic before the start
eg. running condition
'''
pass
def stop(self):
'''
Override to add logic before the stop
eg. invalidating running condition
'''
pass
def main(self):
'''
Main class to be ovverridden to add logic
'''
pass
# entry point of the module: copy and paste into the new module
# ensuring you are calling the "parse_command_line" of the new created class
if __name__ == '__main__':
SMWinservice.parse_command_line()
让我们检查一下我们刚刚介绍的课程。
def SvcDoRun(self):请求服务启动时将调用的方法。
def SvcStop(self):请求服务停止时将调用的方法。
def start(self):这是一种方法,在服务启动时(启动之前),您需要重写是否需要做某事
def stop(self):服务停止时(停止之前)是否需要执行某些操作,将要求您覆盖此方法
def main(self):这是将包含脚本逻辑的方法,通常是在循环中使其保持活动状态直到服务停止。
def parse_command_line(cls):这是处理命令行界面的方法,可用于安装和更新Windows服务
您能看到使用pywin32与系统交互以创建Windows服务有多么容易吗?最后提到的是以下变量:
svc_name = "PythonCornerExample"
svc_display_name = "Python Corner's Winservice Example"
svc_description = "That's a great winservice! :)"
这只是三个变量,其中包含服务的名称,“友好名称”(Windows将使用该名称在mmc控制台上显示名称)以及服务的简短说明。
一如既往,足够多的讨论,让我们编写一些有用的代码!
假设我们要创建一个Winservice,该Winservice在启动时每5秒在C:驱动器上创建一个随机文件。
什么?你觉得这很蠢吗?好了,将其安装在您的老板PC上,将目标文件夹设置为其用户的桌面,您将改变主意。:)
但是,如何才能达到这个结果呢?超级容易。
子类化我们刚刚遇到的SMWinservice类。
在新类上,覆盖三个变量_svc_name_,_svc_display_name_和_svc_description_。
覆盖“开始”方法以设置运行条件。设置一个布尔变量就足够了。
当请求停止服务时,重写“stop”方法以使运行状况无效。
覆盖“main”方法以添加每5秒创建一个随机文件的逻辑
将调用添加到“parse_command_line”函数以处理命令行界面。
结果应该是这样的:
import time
import random
from pathlib import Path
from SMWinservice import SMWinservice
class PythonCornerExample(SMWinservice):
_svc_name_ = "PythonCornerExample"
_svc_display_name_ = "Python Corner's Winservice Example"
_svc_description_ = "That's a great winservice! :)"
def start(self):
self.isrunning = True
def stop(self):
self.isrunning = False
def main(self):
i = 0
while self.isrunning:
random.seed()
x = random.randint(1, 1000000)
Path(f'c:{x}.txt').touch()
time.sleep(5)
if __name__ == '__main__':
PythonCornerExample.parse_command_line()
而已!现在是时候安装我们新创建的winservice了。只需打开命令提示符,导航到脚本目录并使用以下命令安装服务:
C:test>python PythonCornerExample.py install
Installing service PythonCornerExample
Service installed
将来,如果您想更改服务代码,只需对其进行修改并使用以下命令重新安装该服务
C:test>python PythonCornerExample.py update
Changing service configuration
Service updated
现在,打开“服务” msc管理单元
C:test>mmc Services.msc
找到新的PythonCornerExamplewinservice,然后右键单击并选择属性。在这里,您可以启动服务并随意配置。
现在尝试启动服务,然后查看C:文件夹的内容。
您可以看到所有这些文件都已创建到C:文件夹吗?是的,这有效!
但是现在是时候停止它了!:)您可以在以前的窗口中执行此操作,也可以仅使用命令行来执行此操作
C:test>net stop PythonCornerExample
Il servizio Python Corner's Winservice Example sta per essere arrestato..
Servizio Python Corner's Winservice Example arrestato.
如果出问题了...
用Python编写Windows服务可能会发生几个已知的问题。如果您已经成功安装了该服务但启动了该服务,则会收到错误消息,请按照以下步骤对服务进行故障排除:
检查Python是否在您的PATH变量中。它必须在那里。要检查这一点,只需打开命令提示符,然后尝试通过键入“ python”来启动python解释器。如果开始,那很好。
确保具有该文件C:\Program Files\Python36\Lib\site-packages\win32\pywintypes36.dll(请注意,“ 36”是您的Python安装版本)。如果您没有此文件,请从中C:\Program Files\Python36\Lib\site-packages\pywin32_system32\pywintypes36.dll复制并复制到C:\Program Files\Python36\Lib\site-packages\win32
如果仍然有问题,请尝试以调试模式执行Python脚本。要在上一个示例中尝试此操作,请打开一个终端,导航到脚本所在的目录,然后键入
c:test>python PythonCornerExample.py debug
好的,今天就这些,这只是使用Python开发Windows服务的简短介绍。自己尝试一下,…快乐编码!