• 使用Python写Windows Service服务程序


    1.背景

    如果你想用Python开发Windows程序,并让其开机启动等,就必须写成windows的服务程序Windows Service,用Python来做这个事情必须要借助第三方模块pywin32,自己去下载然后安装(注意下载符合自己OS的版本)

    2.实例

    先上代码

    #encoding=utf-8  
    import win32serviceutil   
    import win32service   
    import win32event  
    import os   
    import logging  
    import inspect
    import servicemanager
      
    class PythonService(win32serviceutil.ServiceFramework):   
      
        _svc_name_ = "PythonService"  #服务名 
        _svc_display_name_ = "Python Service Test"  #服务在windows系统中显示的名称
        _svc_description_ = "This is a python service test code "  #服务的描述
      
        def __init__(self, args):   
            win32serviceutil.ServiceFramework.__init__(self, args)   
            self.hWaitStop = win32event.CreateEvent(None, 0, 0, None)  
            self.logger = self._getLogger()  
            self.run = True  
              
        def _getLogger(self):  
              
            logger = logging.getLogger('[PythonService]')  
              
            this_file = inspect.getfile(inspect.currentframe())  
            dirpath = os.path.abspath(os.path.dirname(this_file))  
            handler = logging.FileHandler(os.path.join(dirpath, "service.log"))  
              
            formatter = logging.Formatter('%(asctime)s %(name)-12s %(levelname)-8s %(message)s')  
            handler.setFormatter(formatter)  
              
            logger.addHandler(handler)  
            logger.setLevel(logging.INFO)  
              
            return logger  
      
        def SvcDoRun(self):  
            import time  
            self.logger.info("service is run....")   
            while self.run:  
                self.logger.info("I am runing....")  
                time.sleep(2)  
                  
        def SvcStop(self):   
            self.logger.info("service is stop....")  
            self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)   
            win32event.SetEvent(self.hWaitStop)   
            self.run = False  
      
    if __name__=='__main__':   
        if len(sys.argv) == 1:
            try:
                evtsrc_dll = os.path.abspath(servicemanager.__file__)
                servicemanager.PrepareToHostSingle(PythonService)
                servicemanager.Initialize('PythonService', evtsrc_dll)
                servicemanager.StartServiceCtrlDispatcher()
            except win32service.error, details:
                if details[0] == winerror.ERROR_FAILED_SERVICE_CONTROLLER_CONNECT:
                    win32serviceutil.usage()
        else:
            win32serviceutil.HandleCommandLine(PythonService)

    解释一下代码:

    1).在类PythonService的__init__函数执行完后,系统服务开始启动,windows系统会自动调用SvcDoRun函数,这个函数的执行不可以结束,因为结束就代表服务停止。所以当我们放自己的代码在SvcDoRun函数中执行的时候,必须确保该函数不退出。

    2).当停止服务的时候,系统会调用SvcDoStop函数,该函数通过设置标志位等方式让SvcDoRun函数退出,就是正常的停止服务。例子中是通过event事件让SvcDoRun函数停止等待,从而退出该函数,从而使服务停止。系统关机时不会调用SvcDoStop函数,所以这种服务是可以设置为开机自启的。

    3.服务操作命令

    #1.安装服务
    
    python PythonService.py install
    
    #2.让服务自动启动
    
    python PythonService.py --startup auto install 
    
    #3.启动服务
    
    python PythonService.py start
    
    #4.重启服务
    
    python PythonService.py restart
    
    #5.停止服务
    
    python PythonService.py stop
    
    #6.删除/卸载服务
    
    python PythonService.py remove

    4.使用pyinstaller打包exe

    pyinstaller.exe -F -c winService.py

    效果:

    image

    image

    5.管理windows服务操作

    #!/usr/bin/env python
    # -*- coding: UTF8 -*-
    #
    import win32service
    import win32con
    import time, sys
    import datetime
    reload(sys)
    sys.setdefaultencoding("utf8")
    class ServiceManager(object):
        """管理window服务"""
    
        def __init__(self, name):
            """
            name: 服务的名称
            """
            self.name = name
            
            #启动或停止服务时等待操作成功等待时间
            self.wait_time = 0.5
            #启动或停止服务时最大等待时间,超过时返回超时提示
            self.delay_time = 10
            self.scm = win32service.OpenSCManager(None, None, win32service.SC_MANAGER_ALL_ACCESS)
    
    
            if self.is_exists():
                try:
                    self.handle = win32service.OpenService(self.scm, self.name, win32service.SC_MANAGER_ALL_ACCESS)
                except Exception, e:
                    self.log(e)
            else:
                print '服务 %s 没有安装'.encode('gbk') % self.name
                
    
        def is_stop(self):
            """检查服务是否停止"""
            flag = False
            try:
                if self.handle:
                    ret = win32service.QueryServiceStatus(self.handle)
                    flag = ret[1] != win32service.SERVICE_RUNNING
            except Exception, e:
                self.log(e)
            return flag
    
        def start(self):
            """开启服务"""
            try:
                if self.handle:
                    win32service.StartService(self.handle, None)
            except Exception, e:
                self.log(e)
            status_info = win32service.QueryServiceStatus(self.handle)
    
            if status_info[1] == win32service.SERVICE_RUNNING:
                return '启动服务%s成功'.encode('gbk') % self.name
            elif status_info[1] == win32service.SERVICE_START_PENDING:
                #如果服务正在启动中则延迟返回启动信息,直到启动成功,或返回启动时间过长信息
                start_time = datetime.datetime.now()
                while True:
                    if (datetime.datetime.now() - start_time).seconds > self.delay_time:
                        return '启动服务%s时间太长'.encode('gbk') % self.name
    
                    time.sleep(self.wait_time)
                    if win32service.QueryServiceStatus(self.handle)[1] == win32service.SERVICE_RUNNING:
                        return '启动服务%s成功'.encode('gbk') % self.name
            else:
                return '启动服务%s失败'.encode('gbk') % self.name
    
        def stop(self):
            """停止服务"""
            try:
                status_info = win32service.ControlService(self.handle, win32service.SERVICE_CONTROL_STOP)
            except Exception, e:
                self.log(e)
            if status_info[1] == win32service.SERVICE_STOPPED:
                return '停止服务%s成功'.encode('gbk') % self.name
            elif status_info[1] == win32service.SERVICE_STOP_PENDING:
                start_time = datetime.datetime.now()
                while True:
                    if (datetime.datetime.now() - start_time).seconds > self.delay_time:
                        return '停止服务%s时间太长'.encode('gbk') % self.name
    
                    time.sleep(self.wait_time)
                    if win32service.QueryServiceStatus(self.handle)[1] == win32service.SERVICE_STOPPED:
                        return '停止服务%s成功'.encode('gbk') % self.name
            else:
                return '停止服务%s失败'.encode('gbk') % self.name
    
        def restart(self):
            """重启服务"""
            if not self.is_stop():
                self.stop()
            self.start()
            return win32service.QueryServiceStatus(self.handle)
    
        def status(self):
            """获取运行的状态"""
            try:
                status_info = win32service.QueryServiceStatus(self.handle)
                status = status_info[1]
                if status == win32service.SERVICE_STOPPED:
                    return "STOPPED"
                elif status == win32service.SERVICE_START_PENDING:
                    return "STARTING"
                elif status == win32service.SERVICE_STOP_PENDING:
                    return "STOPPING"
                elif status == win32service.SERVICE_RUNNING:
                    return "RUNNING"
            except Exception, e:
                self.log(e)
    
        def close(self):
            """释放资源"""
            try:
                if self.scm:
                    win32service.CloseServiceHandle(self.handle)
                    win32service.CloseServiceHandle(self.scm)
            except Exception, e:
                self.log(e)
    
        def is_exists(self):
            """windows服务是否已安装"""
            statuses = win32service.EnumServicesStatus(self.scm, win32service.SERVICE_WIN32, win32service.SERVICE_STATE_ALL)
            for (short_name, desc, status) in statuses:
                if short_name == self.name:
                    return True
            return False
    
        def log(self, exception):
            
            print(exception)
            
            
    
    if __name__=='__main__':
    
        app= ServiceManager('PythonService')
        msg= app.is_exists()  # 判断是否安装  (以下操作必须先判断服务是否存在)
        #msg= app.is_stop()  # 判断服务是否停止
        #msg= app.status()  # 查看服务的状态
        #msg= app.start()  # 开启服务
        #msg= app.stop()  # 暂停服务   (服务开启才能停止,else error)
        #msg= app.restart()  # 重启服务
        
        print(msg)
  • 相关阅读:
    73. Set Matrix Zeroes
    289. Game of Live
    212. Word Search II
    79. Word Search
    142. Linked List Cycle II
    141. Linked List Cycle
    287. Find the Duplicate Number
    260. Single Number III
    137. Single Number II
    Oracle EBS中有关Form的触发器的执行顺序
  • 原文地址:https://www.cnblogs.com/zoro-robin/p/6110188.html
Copyright © 2020-2023  润新知