Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I run APScheduler inside a Windows service...I'm almost there

I'm working on a project to run Python APScheduler as a Windows Service with the results going to a text file. I can install and start the service without a hitch.

I've tried a couple of ways of running the scheduler inside a service with the most common and frustrating result being that when I stop the service the scheduler's thread continues to write to the text file. I have to reboot the computer to kill the thread.

I've tried a 'blocking' and 'background' schedulers and they behave the same.

I've played with moving the scheduler.shutdown() into different places. I would like to place it in the service stop function and have the scheduler run until the service receives a stop command whereupon the service stop function would handle shutting down the scheduler.

Perhaps you can point me in the right direction? Here is the code sanitized to ensure you will not have to reboot your computer.

import win32serviceutil
import win32service
import win32event
import servicemanager
import socket
import time
import logging
import configparser
import os

from datetime import datetime
from mysql.connector import errorcode
from apscheduler.schedulers.background import BackgroundScheduler

global FILEPATH
global SERVICE

#Define constants
FILEPATH = os.path.dirname(os.path.realpath(__file__))
SERVICE = 'service.log'

logging.basicConfig(
    filename = '%s\\%s' % (FILEPATH, SERVICE),
    level = logging.DEBUG, 
    format = '[Logging Service] %(levelname)-7.7s %(message)s'
)


def hi(text):
    logging.info(text)
    return

class HelloWorldSvc (win32serviceutil.ServiceFramework):
    _svc_name_ = "Logging-Service"
    _svc_display_name_ = "Logging Service"
    _svc_description_ = "Periodically logs information"

    def __init__(self,args):
        win32serviceutil.ServiceFramework.__init__(self,args)
        self.stop_event = win32event.CreateEvent(None,0,0,None)
        socket.setdefaulttimeout(60)
        self.stop_requested = False

    def SvcStop(self):
        self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)
        win32event.SetEvent(self.stop_event)
        logging.info('Stopping service ...')
        self.stop_requested = True

    def SvcDoRun(self):
        servicemanager.LogMsg(
            servicemanager.EVENTLOG_INFORMATION_TYPE,
            servicemanager.PYS_SERVICE_STARTED,
            (self._svc_name_,'')
        )
        self.main()

    def main(self):
        logging.info(' ** Starting Logging Operation ** ')

        scheduler = BackgroundScheduler()
        scheduler.add_job(hi, 'interval', seconds=5, args=['arg text'])
        scheduler.start()
        time.sleep(15)
        scheduler.shutdown()
        time.sleep(10)

        logging.info('Ended')
        return

if __name__ == '__main__':
    win32serviceutil.HandleCommandLine(HelloWorldSvc)
like image 751
ForgottenKahz Avatar asked Dec 08 '14 05:12

ForgottenKahz


1 Answers

Did you try stopping it like this:

    win32serviceutil.StopService(service, machine)
like image 148
Yavor Avatar answered Oct 12 '22 23:10

Yavor