1. 程式人生 > >windows下基於Python的定時服務程式

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的環境中運行了。