设为首页 收藏本站
查看: 647|回复: 0

[经验分享] 使用Python写Windows Service服务程序

[复制链接]

尚未签到

发表于 2017-6-29 06:09:13 | 显示全部楼层 |阅读模式
  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
  效果:
DSC0000.png

DSC0001.png

  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)

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-389115-1-1.html 上篇帖子: kali linux 更新软件源,安装中文输入法,修复Linux与windows引导菜单解决windows引导丢失 下篇帖子: python--windows下安装BeautifulSoup
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表