windows下基于Python的定时服务程序

写在前面

假设你在阅读本文时,已经具有了在windows平台安装Python以及Python第三方模块的能力。

Linux平台下面有crontab可以做系统的定时任务, windows下也有对应的定时任务。之前做一个项目,通过windows的计划任务调用php脚本定时给满足条件的用户发送邮件,但是定时任务执行的很不稳定,且针对每个任务都需要做一个单独的定时器,配置比较麻烦,还容易出错。于是就想到了用Python脚本做一个服务程序用来执行定时任务。

做Python定时服务程序首先要解决一下几个问题
1 如何用Python编写windows服务程序?
2 如何定义定时任务?(本文借鉴Linux的crontab,进行定时任务的定义)
3 如何实现通用?(web开发中需要执行定时任务的需求也比较多)
4 如何脱离Python环境单独运行?(用pyinstaller打包exe)

下面从上面4个方面讲述以下我的Python定时服务程序的实现过程,文后附实现的代码

基于Python的windows 服务程序的编写

用Python来做windows服务程序必须要借助第三方模块pywin32,可以通过pip安装。先上代码,

#!/usr/bin/python
# -*- coding: utf8 -*-

import win32service
import win32serviceutil
import win32event
import servicemanager
import os, sys, time
from smco_croniter import SMCOSched  

class CronDaemon(win32serviceutil.ServiceFramework):
    # you can NET START/STOP the service by the following name
    _svc_name_ = "Cron Daemon"
    # this text shows up as the service name in the Service
    # Control Manager (SCM)
    _svc_display_name_ = "Cron Daemon"
    # this text shows up as the description in the SCM
    _svc_description_ = "Cron Daemon for scheduled tasks"

    def __init__(self, args):
        win32serviceutil.ServiceFramework.__init__(self,args)
        self.hWaitStop = win32event.CreateEvent(None, 0, 0, None)       
        self.isAlive = True

    def SvcDoRun(self): 
        while self.isAlive:
            print "your code"
            time.sleep(10)

    def SvcStop(self):
      self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)
        win32event.SetEvent(self.hWaitStop)
        self.isAlive = False 

if __name__ == "__main__":

    if len(sys.argv) == 1:
        try:
            evtsrc_dll = os.path.abspath(servicemanager.__file__)
            servicemanager.PrepareToHostSingle(CronDaemon)
            servicemanager.Initialize('CronDaemon', evtsrc_dll)
            servicemanager.StartServiceCtrlDispatcher()
        except win32service.error, details:
            if details[0] == winerror.ERROR_FAILED_SERVICE_CONTROLLER_CONNECT:
                win32serviceutil.usage()
    else:
        win32serviceutil.HandleCommandLine(CronDaemon)

用Python实现windows服务程序还是比较简单的,只需要继承win32serviceutil.ServiceFramework 类即可,而我们需要做的就是在继承的类中调用我们需要定时执行的代码。上面的代码在网上有很多,几乎成为了一个模板,这里不再深入的讲述。

如何定义定时任务?

windows上的定时任务配置比较麻烦,而Linux的cron实现的定时任务就比较简单,只需要配置执行的时间和命令即可,基本格式如下(详情请参考,Linux定时任务

分 时 天 月 周 命令

每分钟执行一次,可以写成, */1 * * * * cmd
每天上午8点执行一次, 可以写成,0 8 */1 * * cmd

因此,我们可以利用linux的cron 定义计划任务。那如何解析cron的计划呢?很幸运,Python已经提供了这个模块,croniter,我们使用 pip install croniter即可安装croniter模块。

至此,就可以利用croniter解析Linux cron格式的计划任务了,而我们只需将计划任务写入到文件中,再有Python读取即可。我定义的计划任务格式如下:

配置文件

croniter的使用方法如下:

croniter.croniter(sched,basetime)

只需要传入计划任务sched,和计划的开始时间,就可以计算出下一次需要执行的时间,如执行

croniter.croniter("*/5 * * * *","2017-01-04 19:43")

那么计算出的定时任务的下一次执行时间就是,2017-01-04 19:48

如何实现通用?

本文类之间的关系如下图所示,

这里写图片描述

很惭愧,在我的代码中并没有实现通用,这里我提供一个重构的思路,欢迎大家来一起讨论。

这里写图片描述

我的思路是将任务抽象成一个接口TaskInterface,以后每添加一个新的定时任务,直接继承TaskInterface,并实现接口中的方法即可。

如何脱离Python环境单独运行?

这个问题比较容易解决,使用PyInstaller,将Python的程序打包成一个exe即可,然后就可以在没有安装Python的环境中运行了。

也可以参考一下我的这篇博客,http://blog.csdn.net/guoxiaojie_415/article/details/50988943

源码下载地址:http://download.csdn.net/detail/guoxiaojie_415/9729020

猜你喜欢

转载自blog.csdn.net/guoxiaojie_415/article/details/54022807