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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章