Using configparser in Python service is not starting the service

296 Views Asked by At

I have used configparser to read a configuration file in python. When the script is converted to Windows Service it is giving error saying "Error starting service: The service did not respond to the start or control request in a timely fashion." I have increased ServicesPipeTimeout and enabled Allow service to interact with desktop but it did not solve the issue.

The script is

import logging
import configparser
import mysql.connector
import socket
import win32event
import win32service
import servicemanager
import win32serviceutil
import sys



logging.basicConfig(
    filename = "C:\\Users\\Administrator\\PythonService.txt",
    level = logging.INFO,
    format = '%(asctime)s - %(name)s - %(levelname)s - %(message)s',
    datefmt='%m/%d/%Y %I:%M:%S %p'
)


def main():
    configaration = configparser.ConfigParser()
    configaration.read('default.ini')
    host = configaration['mysql']['host']
    username = configaration['mysql']['user']
    password = configaration['mysql']['password']
    database = configaration['mysql']['database']
    config = {'user': username,'password': password,'host': host,'database': database}
    logging.info(config)

class TestService(win32serviceutil.ServiceFramework):
    _svc_name_ = "ClientService"
    _svc_display_name_ = "Client Service"

    def __init__(self, args):
        win32serviceutil.ServiceFramework.__init__(self, args)
        self.hWaitStop = 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.hWaitStop)
        logging.info('Stopping service ....')
        self.stop_requested = True

    def SvcDoRun(self):
        logging.info("Started service")
        servicemanager.LogMsg(servicemanager.EVENTLOG_INFORMATION_TYPE,
                              servicemanager.PYS_SERVICE_STARTED,
                              (self._svc_name_, ''))

        rc = None
        while rc != win32event.WAIT_OBJECT_0:
            rc = win32event.WaitForSingleObject(self.hWaitStop, 5000)
            if rc == win32event.WAIT_OBJECT_0:
                servicemanager.LogInfoMsg(servicemanager.EVENTLOG_INFORMATION_TYPE,
                                          servicemanager.PYS_SERVICE_STARTED,

                                          (self._svc_name_, ''))
                break
            else:
                main()


if __name__ == '__main__':
    if len(sys.argv) == 1:
        servicemanager.Initialize()
        servicemanager.PrepareToHostSingle(TestService)
        servicemanager.StartServiceCtrlDispatcher()
    else:
        win32serviceutil.HandleCommandLine(TestService)

The execution stops when script starts interacting with the file in the filesystem.

1

There are 1 best solutions below

0
On

I have the same issue. If it can to help you, you can try to debug it after the installation. It worked for me, but it's not how I should run it.

To do it, start command prompt as administrator, then write these commands

python Path/to/file.py install

python Path/to/file.py debug

Then you'll see your service running in the prompt.

My problem did not show when I did this, but after installation, I could not start the service from service.msd if I have in my code the method get of configparser, but not only reading data. I think that the problem is about virtual envirovments or privileges, but I did not solve it running it as administrator.

EDIT:

I solved my problem and maybe this could solve your problem too. When you run your program as a service, it run in C:\Windows\System32 , so the current path is not where your python file is stored. When you try to read a config file using configparser, it silently fail and you can't notice that until you try to store the data you read from configuration file. You could try to insert a "try...except" to your code to identify which error stop your service start. If the error is a "NoSection Error", it mean that when you try to use data readed from config file, it failed. You could try to add a print of the current directory in your log, so you can see where the program run, and then move your .ini file in there or try to use an absolute path. NOTE: If you use a dinamically path you could have same issue (that was my problem). If you try to get the user path, you get "C:\Windows\System32\config\systemprofile"

This is an example of what you could implement to solve your problem

...
import os
...
def main():
    configaration = configparser.ConfigParser()
    configaration.read('default.ini')
    try:
        host = configaration['mysql']['host']
        username = configaration['mysql']['user']
        password = configaration['mysql']['password']
        database = configaration['mysql']['database']
        config = {'user': username,'password': password,'host': host,'database': database}
        logging.info(config)
    except Exception as e:
        logging.info(f"\nError: {e}\nCurrent Directory: {os.getcwd()}")
...