首先让我们开始安装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

现在,打开“服务” m​​sc管理单元

C:test> mmc Services.msc

找到新的PythonCornerExample winservice,然后右键单击并选择属性。在这里,您可以启动服务并随意配置。

现在尝试启动服务,然后查看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服务的简短介绍。自己尝试一下,…快乐编码!

posted on 2020-11-05 20:44  青·丝  阅读(1368)  评论(0)    收藏  举报