Any more it seems that virtually all the code I write on the windows platform ends up being a windows service. It's just the nature of the kind of work I do: the underappreciated guts that sit far beneath the software that users directly interact with. Obviously windows services are typically written in mainstream .Net languages like C# or VB these days but it's also easy if not easier to do in Python.
Once your Python environment meets the requirements outlined above you're ready to write your service. All you have to do is write an extension of the ServiceFramework class that overrides the SvcDoRun and SvcStop methods. As you can guess SvcDoRun performs the core logic of your service and SvcStop shuts it down.
I've created a sample service below that simply writes some text to a file every five seconds until the service is stopped. Note that this example uses windows signal events to trigger service shutdown via the CreateEvent, WaitForSingleObject and SetEvent windows API calls. Thank you Windows Extensions!
import win32service import win32serviceutil import win32event class PySvc(win32serviceutil.ServiceFramework): # you can NET START/STOP the service by the following name _svc_name_ = "PySvc" # this text shows up as the service name in the Service # Control Manager (SCM) _svc_display_name_ = "Python Test Service" # this text shows up as the description in the SCM _svc_description_ = "This service writes stuff to a file" 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) # core logic of the service def SvcDoRun(self): import servicemanager f = open('test.dat', 'w+') rc = None # if the stop event hasn't been fired keep looping while rc != win32event.WAIT_OBJECT_0: f.write('TEST DATA\n') f.flush() # block for 5 seconds and listen for a stop event rc = win32event.WaitForSingleObject(self.hWaitStop, 5000) f.write('SHUTTING DOWN\n') f.close() # called when we're being shut down def SvcStop(self): # tell the SCM we're shutting down self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING) # fire the stop event win32event.SetEvent(self.hWaitStop) if __name__ == '__main__': win32serviceutil.HandleCommandLine(PySvc)
Now that the service itself is written we can install it as follows:
C:\Dev\Projects\PySvc> python.exe .\PySvc.py install
That's it! The service can now be started from the command line by
C:\Dev\Projects\PySvc> NET START PySvc
or from the Service Control Manager
Mon Nov 02 2009 20:11:00 GMT+0000 (UTC)