[python-win32] pywin32 services

Roberto Aguilar roberto.c.aguilar at gmail.com
Tue Jul 20 00:53:33 CEST 2010


On Jul 19, 2010, at 5:39 AM, Michael Mileusnich wrote:
> Hello,
> 
> I am trying to run my app as a windows service however I run
> into the following problem:
> 
> Traceback (most recent call last):
>   File "hqmonitor.py", line 220, in<module>
>   File "win32serviceutil.pyc", line 528, in HandleCommandLine
>   File "win32serviceutil.pyc", line 468, in GetServiceClassString
> IndexError: list index out of range
> 
> Can anybody shed some light on this?
> 
> Python 2.6 Windows XP SP2

I'm not familiar with your particular error, but I am successfully running a python service under Windows and can show you what I did to get it working.

I found the following snippets in similar form on the internets somewhere (unfortunately, I don't know from where).

First, make sure you have pywin32.  Since you're asking on this list, I presume you already have it.

Next, there's the instart() function, which installs and starts the service [1].

Then, there's your particular service.  You can extend the base class below [2] and define the start() and stop() methods as you need them.

For example, I have a python app that I run using Popen.  My subclass looks something like:

class MyService(Service):
    _svc_name = 'myservice'
    _svc_display_name_ = 'My Python Service'
    [...]
    def start(self):
        self.ric = Popen(self.COMMAND, env=os.environ)

    def stop(self):
        self.ric.terminate()

Finally, the script that installs and starts the service for the first time:

#!/usr/bin/env python
import sys

from yourmodule import MyService, instart

instart(MyService)

After you run that the first time, you can start stop the service from the management console or using the net command (using the name defined in _svc_name):

net stop myservice
net start myservice

Hope this helps,
-Roberto.

[1] the instart function:

import pywintypes

from os.path import splitext, abspath
from sys import modules

import win32api
import win32service
import win32serviceutil

def instart(cls, stay_alive=True):
    """
    Install and  Start (auto) a Service

    cls : the class (derived from Service) that implement the Service
    name : Service name
    display_name : the name displayed in the service manager
    stay_alive : Service will stop on logout if False
    """

    try:
        module_path = modules[cls.__module__].__file__
    except AttributeError:
        # maybe py2exe went by
        from sys import executable
        module_path = executable

    module_file = splitext(abspath(module_path))[0]
    cls._svc_reg_class_ = '%s.%s' % (module_file, cls.__name__)
    if stay_alive:
        win32api.SetConsoleCtrlHandler(lambda x: True, True)
    try:
        win32serviceutil.InstallService(
            cls._svc_reg_class_,
            cls._svc_name_,
            cls._svc_display_name_,
            startType = win32service.SERVICE_AUTO_START
            )
    except pywintypes.error, msg:
        # error 1073 is for 'CreateService', 'The specified service already
        # exists.'  if we don't get this error, raise it
        if msg[0] != 1073:
            raise

    try:
        win32serviceutil.StartService(cls._svc_name_)
    except Exception, x:
        print x.__class__
        print str(x)

[2] The base service class

import win32api
import win32event
import win32service
import win32serviceutil

class Service(win32serviceutil.ServiceFramework):
    _svc_name_ = '_unNamed'
    _svc_display_name_ = 'Python Service Template'

    def __init__(self, *args):
        win32serviceutil.ServiceFramework.__init__(self, *args)
        self.log('init')
        self.stop_event = win32event.CreateEvent(None, 0, 0, None)

    def log(self, msg):
        import servicemanager
        servicemanager.LogInfoMsg(str(msg))

    def sleep(self, sec):
        win32api.Sleep(sec*1000, True)

    def SvcDoRun(self):
        self.ReportServiceStatus(win32service.SERVICE_START_PENDING)
        try:
            self.ReportServiceStatus(win32service.SERVICE_RUNNING)
            #self.log('start')
            self.start()
            #self.log('wait')
            win32event.WaitForSingleObject(self.stop_event, win32event.INFINITE)
            #self.log('done')
        except Exception, x:
            self.log('Exception : %s' % x)
            self.SvcStop()

    def SvcStop(self):
        self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)
        #self.log('stopping')
        self.stop()
        #self.log('stopped')
        win32event.SetEvent(self.stop_event)
        self.ReportServiceStatus(win32service.SERVICE_STOPPED)

    # to be overridden
    def start(self): pass

    # to be overridden
    def stop(self): pass



More information about the python-win32 mailing list