次のリンクに記載されている解決策を実行して、実行中の日数後に停止しようとするとSTOPPING状態でハングしないWindowsサービスを作成します。PythonでのWindowsサービス
Timeout and Windows Services for Long Running Processes (Python)
私が直面しています問題は、私は一度だけ実行するように思わサービスとWindowsサービスマネージャでサービスを開始した後にすべてのタスクが私はそれを停止または再起動することはできません無効にしているということです。以下は私のコードです。実行したい実際のタスクをすべて削除し、実行するたびに変数(x)に1を加えてログファイルに書き込むダミーサービスで置き換えます。
私は自分の間違いがどこにあるのかを見つけようとしています。
# -*- 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の2番目のパラメータは、すべてのオブジェクトを待機する必要があるかどうかを判断するブール値です。誤ってこの引数に 'INFINITE'(-1)を渡しています。これは真の値なので、waitは常に両方のイベントが設定されていなければ' WAIT_TIMEOUT'(258)を返します。 – eryksun
しかし、これはrc = win32event.WaitForSingleObject(self.hWaitStop、10000)を使用した場合にも発生します。 – Dariva
タイムアウトを提供しています。タイムアウトが必要ない場合は、 'win32event.WaitForMultipleObjects([self.hWaitStop、self.hWaitDone]、False、win32event.INFINITE)'を使用してください。 – eryksun