Python建立Windows服務
首先讓我們開始安裝Python for Windows擴充套件:
c:test> pip install pywin32
完成後,讓我們編寫該基類,您的Windows服務將是該基類的子類。
'''
SMWinservice
by Davide Mastromatteo
Base class to create winservice in Python
-----------------------------------------
Instructions:
1. Just create a new class that inherits from this base class
2. Define into the new class the variables
_svc_name_ = "nameOfWinservice"
_svc_display_name_ = "name of the Winservice that will be displayed in scm"
_svc_description_ = "description of the Winservice that will be displayed in scm"
3. Override the three main methods:
def start(self) : if you need to do something at the service initialization.
A good idea is to put here the inizialization of the running condition
def stop(self) : if you need to do something just before the service is stopped.
A good idea is to put here the invalidation of the running condition
def main(self) : your actual run loop. Just create a loop based on your running condition
4. Define the entry point of your module calling the method "parse_command_line" of the new class
5. Enjoy
'''
import socket
import win32serviceutil
import servicemanager
import win32event
import win32service
class SMWinservice(win32serviceutil.ServiceFramework):
'''Base class to create winservice in Python'''
_svc_name_ = 'pythonService'
_svc_display_name_ = 'Python Service'
_svc_description_ = 'Python Service Description'
@classmethod
def parse_command_line(cls):
'''
ClassMethod to parse the command line
'''
win32serviceutil.HandleCommandLine(cls)
def __init__(self, args):
'''
Constructor of the winservice
'''
win32serviceutil.ServiceFramework.__init__(self, args)
self.hWaitStop = win32event.CreateEvent(None, 0, 0, None)
socket.setdefaulttimeout(60)
def SvcStop(self):
'''
Called when the service is asked to stop
'''
self.stop()
self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)
win32event.SetEvent(self.hWaitStop)
def SvcDoRun(self):
'''
Called when the service is asked to start
'''
self.start()
servicemanager.LogMsg(servicemanager.EVENTLOG_INFORMATION_TYPE,
servicemanager.PYS_SERVICE_STARTED,
(self._svc_name_, ''))
self.main()
def start(self):
'''
Override to add logic before the start
eg. running condition
'''
pass
def stop(self):
'''
Override to add logic before the stop
eg. invalidating running condition
'''
pass
def main(self):
'''
Main class to be ovverridden to add logic
'''
pass
# entry point of the module: copy and paste into the new module
# ensuring you are calling the "parse_command_line" of the new created class
if __name__ == '__main__':
SMWinservice.parse_command_line()
讓我們檢查一下我們剛剛介紹的課程。
def SvcDoRun(self):請求服務啟動時將呼叫的方法。
def SvcStop(self):請求服務停止時將呼叫的方法。
def start(self):這是一種方法,在服務啟動時(啟動之前),您需要重寫是否需要做某事
def stop(self):服務停止時(停止之前)是否需要執行某些操作,將要求您覆蓋此方法
def main(self):這是將包含指令碼邏輯的方法,通常是在迴圈中使其保持活動狀態直到服務停止。
def parse_command_line(cls):這是處理命令列介面的方法,可用於安裝和更新Windows服務
您能看到使用pywin32與系統互動以建立Windows服務有多麼容易嗎?
svc_name = "PythonCornerExample"
svc_display_name = "Python Corner's Winservice Example"
svc_description = "That's a great winservice! :)"
這只是三個變數,其中包含服務的名稱,“友好名稱”(Windows將使用該名稱在mmc控制檯上顯示名稱)以及服務的簡短說明。
一如既往,足夠多的討論,讓我們編寫一些有用的程式碼!
假設我們要建立一個Winservice,該Winservice在啟動時每5秒在C:驅動器上建立一個隨機檔案。
什麼?你覺得這很蠢嗎?好了,將其安裝在您的老闆PC上,將目標資料夾設定為其使用者的桌面,您將改變主意。:)
但是,如何才能達到這個結果呢?超級容易。
- 子類化我們剛剛遇到的SMWinservice類。
- 在新類上,覆蓋三個變數_svc_name_,_svc_display_name_和_svc_description_。
- 覆蓋“開始”方法以設定執行條件。設定一個布林變數就足夠了。
- 當請求停止服務時,重寫“stop”方法以使執行狀況無效。
- 覆蓋“main”方法以新增每5秒建立一個隨機檔案的邏輯
- 將呼叫新增到“parse_command_line”函式以處理命令列介面。
結果應該是這樣的:
import time
import random
from pathlib import Path
from SMWinservice import SMWinservice
class PythonCornerExample(SMWinservice):
_svc_name_ = "PythonCornerExample"
_svc_display_name_ = "Python Corner's Winservice Example"
_svc_description_ = "That's a great winservice! :)"
def start(self):
self.isrunning = True
def stop(self):
self.isrunning = False
def main(self):
i = 0
while self.isrunning:
random.seed()
x = random.randint(1, 1000000)
Path(f'c:{x}.txt').touch()
time.sleep(5)
if __name__ == '__main__':
PythonCornerExample.parse_command_line()
而已!現在是時候安裝我們新建立的winservice了。只需開啟命令提示符,導航到指令碼目錄並使用以下命令安裝服務:
C:test> python PythonCornerExample.py install
Installing service PythonCornerExample
Service installed
將來,如果您想更改服務程式碼,只需對其進行修改並使用以下命令重新安裝該服務
C:test> python PythonCornerExample.py update
Changing service configuration
Service updated
現在,開啟“服務” msc管理單元
C:test> mmc Services.msc
找到新的PythonCornerExamplewinservice,然後右鍵單擊並選擇屬性。在這裡,您可以啟動服務並隨意配置。
現在嘗試啟動服務,然後檢視C:資料夾的內容。
您可以看到所有這些檔案都已建立到C:資料夾嗎?是的,這有效!
但是現在是時候停止它了!:)您可以在以前的視窗中執行此操作,也可以僅使用命令列來執行此操作
C:test> net stop PythonCornerExample
Il servizio Python Corner's Winservice Example sta per essere arrestato..
Servizio Python Corner's Winservice Example arrestato.
如果出問題了...
用Python編寫Windows服務可能會發生幾個已知的問題。如果您已經成功安裝了該服務但啟動了該服務,則會收到錯誤訊息,請按照以下步驟對服務進行故障排除:
- 檢查Python是否在您的PATH變數中。它必須在那裡。要檢查這一點,只需開啟命令提示符,然後嘗試通過鍵入“ python”來啟動python直譯器。如果開始,那很好。
- 確保具有該檔案
C:\Program Files\Python36\Lib\site-packages\win32\pywintypes36.dll
(請注意,“ 36”是您的Python安裝版本)。如果您沒有此檔案,請從中C:\Program Files\Python36\Lib\site-packages\pywin32_system32\pywintypes36.dll
複製並複製到C:\Program Files\Python36\Lib\site-packages\win32
如果仍然有問題,請嘗試以除錯模式執行Python指令碼。要在上一個示例中嘗試此操作,請開啟一個終端,導航到指令碼所在的目錄,然後鍵入
c:test> python PythonCornerExample.py debug
好的,今天就這些,這只是使用Python開發Windows服務的簡短介紹。自己嘗試一下,…快樂編碼!