我正在關注下面鏈接中提供的解決方案,以便在運行一些日子後嘗試停止它時不會以STOPPING狀態掛起的Python創建Windows服務。Python中的Windows服務
Timeout and Windows Services for Long Running Processes (Python)
我現在面臨的問題是,當我啓動該服務似乎只運行一次,並在Windows服務管理服務已全部任務禁止,所以我不能停止或重新啓動它。以下是我的代碼。我已經刪除了所有我想要執行的實際任務,並將其替換爲一個虛擬服務,該虛擬服務每次運行時將1添加到變量(x)並將其寫入日誌文件。
我會很感激任何提示試圖找到我在哪裏是我的錯誤。
# -*- coding: utf-8 -*-
"""
Created on Thu Jul 27 09:07:29 2017
@author:aaaa
"""
import threading
import logging
import logging.config
import win32api
import win32serviceutil
import win32event
class InterruptedException(Exception):
pass
class WorkerThread(threading.Thread):
def __init__(self, controller):
self._controller = controller
self._stop = threading.Event()
super(WorkerThread, self).__init__()
self.x=0
#------------------------------------------------------------------------------
# Creating logger
#------------------------------------------------------------------------------
logging.config.fileConfig(r'c:\temp\teste_logging.conf')
# create logger
self.logger = logging.getLogger('teste')
self.logger.debug("Serviço criado")
def stop(self):
self._stop.set()
def stopped(self):
return self._stop.isSet()
def run(self):
try:
# Insert the code you want to run as a service here
# rather than do "execfile(.../.../blah)" simply do:
# You can have your code throw InterruptedException if your code needs to exit
# Also check often if self.stopped and then cleanly exit
self.x+=1
self.logger.debug('x = {}'.format(self.x))
except InterruptedException as e:
# We are forcefully quitting
self.logger.debug('Interruption Exception - {}'.format(str(e)))
pass
except Exception as e:
self.logger.debug('Unexpected Error - {}'.format(str(e)))
pass
# Oh oh, did not anticipate this, better report to Windows or log it
finally:
# Close/release any connections, handles, files etc.
# OK, we can stop now
win32event.SetEvent(self._controller)
class test_service(win32serviceutil.ServiceFramework):
_svc_name_ = "pyTEST"
_svc_display_name_ = "TEST Event service"
_svc_description_ = "Service to teste python service"
def __init__(self, args):
win32serviceutil.ServiceFramework.__init__(self, args)
self.hWaitStop = win32event.CreateEvent(None, 0, 0, None)
self.hWaitDone = win32event.CreateEvent(None, 0, 0, None)
#logger
self.logger=logging.getLogger('teste.SERVICE')
#create worker
self.worker = WorkerThread(self.hWaitDone)
def SvcDoRun(self):
import servicemanager
servicemanager.LogMsg(servicemanager.EVENTLOG_INFORMATION_TYPE,
servicemanager.PYS_SERVICE_STARTED,(self._svc_name_, ''))
#worker = WorkerThread(self.hWaitDone,self.dCONFIG)
self.worker.start()
while True:
# Wait for service stop signal
rc = win32event.WaitForMultipleObjects([self.hWaitStop, self.hWaitDone],win32event.INFINITE,60000)
# Check to see if self.hWaitStop happened as part of Windows Service Management
if rc == 0:
# Stop signal encountered
servicemanager.LogInfoMsg(self._svc_name_ + " - STOPPED!") #For Event Log
break
if rc == 1:
# Wait until worker has fully finished
self.worker.join()
# Determine from worker state if we need to start again (because run finished)
# Or do whatever
if not self.worker.need_to_start_again():
break
self.worker.start()
def ctrlHandler(ctrlType):
return True
if __name__ == '__main__':
win32api.SetConsoleCtrlHandler(ctrlHandler, True)
win32serviceutil.HandleCommandLine(test_service)
這裏是日誌記錄模塊的配置。只需將其保存在文本文件中並將其保存爲teste_logging.conf
[loggers]
keys=root,teste
[handlers]
keys=logfile,consoleHandler
[formatters]
keys=simpleFormatter,logfileformatter
[logger_root]
level=DEBUG
handlers=consoleHandler
[logger_teste]
level=DEBUG
handlers=logfile
qualname=teste
propagate=0
[formatter_logfileformatter]
format=%(asctime)s %(name)-12s: %(levelname)s %(message)s
[formatter_simpleFormatter]
format=%(asctime)s - %(name)s - %(levelname)s - %(message)s
datefmt=
[handler_consoleHandler]
class=StreamHandler
level=DEBUG
formatter=simpleFormatter
args=(sys.stdout,)
[handler_logfile]
class=handlers.RotatingFileHandler
level=DEBUG
args=(r'C:\temp\pyteste.log','a',5000000,20)
formatter=logfileformatter
'WaitForMultipleObjects'的第二個參數是一個布爾值,它決定了它是否應該等待所有對象。您錯誤地將'INFINITE'(-1)傳遞給了這個參數,這是一個真實的值,所以等待總是返回WAIT_TIMEOUT(258),除非偶然事件被設置。 – eryksun
但是,如果我使用rc = win32event.WaitForSingleObject(self.hWaitStop,10000) – Dariva
,也會發生這種情況您提供了一個超時時間,我假設在循環中執行其他操作,然後再次等待。如果您不想超時,請使用'win32event.WaitForMultipleObjects([self.hWaitStop,self.hWaitDone],False,win32event.INFINITE)''。 – eryksun