[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