NOTE: This post was originally written in 2009 so it may be dated. I’m resurrecting it due to relative popularity. This post has been copied between several blogging systems (some of which were home-brewed) and some formatting has been lost along the way.
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.
Requirements
- A Python Interpreter – this one’s pretty obvious. Can’t run Python code without a Python interpreter.
- Python for Windows Extensions – this is a wonderful, easy to install project that exposes the innards of windows to Python.
- Administrative access – you must be logged in with administrative access in order to install your service.
The Code
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)
Service Installation
Now that the service itself is written we can install it as follows:
C:\Dev\Projects\PySvc>python.exe .\PySvc.py install
Service Control
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