博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
使用Python写Windows Service服务程序
阅读量:7081 次
发布时间:2019-06-28

本文共 7613 字,大约阅读时间需要 25 分钟。

1.背景

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

2.实例

先上代码

#encoding=utf-8  import win32serviceutil   import win32service   import win32event  import os   import logging  import inspectimport 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

效果:

5.管理windows服务操作

#!/usr/bin/env python# -*- coding: UTF8 -*-#import win32serviceimport win32conimport time, sysimport datetimereload(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)

 

转载于:https://www.cnblogs.com/POSLINKS/p/8280320.html

你可能感兴趣的文章
Linux epoll版定时器
查看>>
objective C中数据持久化方式1--对象归档
查看>>
Python面向对象编程 - 一个记事本程序范例(一)
查看>>
马桶餐厅
查看>>
我对程序员技能的一些认识
查看>>
在linux下如何修改oracle的sys和system的密码
查看>>
【C语言】01-C语言概述
查看>>
mysql FullText全文索引的问题
查看>>
空格&nbsp在不同浏览器中显示距离不一致问题解决方法
查看>>
Dynamic CRM 2013学习笔记(八)过滤查找控件 (类似省市联动)
查看>>
iOS执行时与method swizzling
查看>>
SQL点滴21—几个有点偏的语句
查看>>
Android各种效果集合
查看>>
【转】Geary's C
查看>>
Linux中查看socket状态(转)
查看>>
public-private-protected-默认缺省 的区别
查看>>
React Native上手
查看>>
0919 - iPaste 上架 App Store
查看>>
iKcamp&掘金Podcast直播回顾(12月2号和9号的两场)
查看>>
Java简短知识点
查看>>