为什么我的子类将我的python服务无法在Windows上启动?

时间:2018-01-31 12:21:15

标签: python windows service subclass

我想在Windows上运行一些Python代码作为服务。我顺便使用Python 3.6。 我把这个通用的Windows守护进程类放在一起(来自各种来源)。当我运行它,它运作良好。但是,当我将其子类化为在包含一些实际有用代码的服务中使用时,服务未启动但立即返回 ,错误服务未响应启动或控制请求及时的时尚

所以 - 请参阅下面的示例 - windows_daemon.py 有效,但 new_service.py 却没有。

当我将它子类化时,有谁​​可以看到为什么我的python服务没有在Windows上启动?

windows_daemon.py

import time
import sys
import logging
import logging.handlers
import traceback
import win32serviceutil
import win32service
import win32event
import servicemanager
import os

def handle(instance):
    win32serviceutil.HandleCommandLine(instance)
class windows_daemon(win32serviceutil.ServiceFramework):
    # you can NET START/STOP the service by the following name  
    _svc_name_ = "Daemon"
    # this text shows up as the service name in the Service  
    # Control Manager (SCM)
    _svc_display_name_ = "Windows daemon"
    # this text shows up as the description in the SCM  
    _svc_description_ = "This service controls some stuff"
    # list dependencies
    _svc_deps_ = ["EventLog"]

    def __init__(self, args):
        win32serviceutil.ServiceFramework.__init__(self,args)

        # create an event to listen for stop requests on 
        self.hWaitStop = win32event.CreateEvent(None,0,0,None)
        self.Alive = True
        self.host = os.environ['COMPUTERNAME'].lower()
        self.pid = os.getpid()
        self.name = self._svc_display_name_
        self.rootlogger = logging.getLogger()
        #self.logger = logging.getLogger("{}".format(self.name))
        self.rootlogger.setLevel(logging.DEBUG)
        formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
        handler = logging.handlers.RotatingFileHandler("{0}\log\{1}.log".format(os.path.dirname(os.path.realpath(__file__)), self.name), maxBytes = 1000000, backupCount = 5)
        handler.setFormatter(formatter)
        self.rootlogger.addHandler(handler)
        self.logger = logging.getLogger("service")

    # called when we're being shut down   
    def SvcStop(self):
        self.logger.info("stopping service")

        # tell the SCM we're shutting down
        self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)
        # fire the stop event
        win32event.SetEvent(self.hWaitStop)
        self.Alive = False

    # core logic of the service   
    def SvcDoRun(self):
        self.ReportServiceStatus(win32service.SERVICE_RUNNING)
        servicemanager.LogMsg(servicemanager.EVENTLOG_INFORMATION_TYPE,
                              servicemanager.PYS_SERVICE_STARTED,
                              (self._svc_name_, ''))
        self.logger.debug("starting service")
        self.timeout = 100
        try:
            self.main()
            self.logger.debug("no exception in main")
            exitcode = 0
        except Exception as e:
            #could also debug to Windows event log
            #servicemanager.LogErrorMsg(traceback.format_exc())
            #servicemanager.LogErrorMsg("{}".format(e))
            try:
                self.logger.error(e)
                self.logger.error(traceback.format_exc())
            except Exception as e:
                pass
                # servicemanager.LogErrorMsg("{}".format(e))
            #return some value other than 0 to os so that service knows to restart
            self.logger.error("some exception in main")
            exitcode = -1
        servicemanager.LogMsg(servicemanager.EVENTLOG_INFORMATION_TYPE,
                              servicemanager.PYS_SERVICE_STOPPED,
                              (self._svc_name_, ''))
        self.ReportServiceStatus(win32service.SERVICE_STOPPED)
        self.logger.info("stopped with exit code {}".format(exitcode))
        os._exit(exitcode)
    def check_for_signals(self, timeout = 100):
        rc = win32event.WaitForSingleObject(self.hWaitStop, self.timeout)
    def main(self):
        # override in subclass
        print("this is function main() that should be subclassed")
        #time.sleep(1)
        pass

if __name__ == '__main__':
    handle(windows_daemon)
    print("you should subclass windows_daemon from this module")

new_service.py

from windows_daemon import windows_daemon, handle
import time
import sys
import win32serviceutil
class New_service(windows_daemon):
    # you can NET START/STOP the service by the following name  
    _svc_name_ = "NEW"
    # this text shows up as the service name in the Service  
    # Control Manager (SCM)
    _svc_display_name_ = "New service"
    # this text shows up as the description in the SCM  
    _svc_description_ = "This service exists as a template for new services"
    # override dependencies?
    # _svc_deps_ = ["EventLog"]
    def __init__(self, args):
        print(super())
        super().__init__(args)
    def main(self):
        time.sleep(10)
if __name__ == '__main__':
    sys.frozen = 'windows_exe'
    handle(New_service)

1 个答案:

答案 0 :(得分:0)

显然,这条线引起了这个问题。我发现通过了解python调试模块(pdb)并使用它进行调查。

sys.frozen = 'windows_exe'

当我删除此行时, new_service.py 也会运行。希望这可以帮助将来的某个人。