CherryPy Project Download

CherryPy as a Windows Service

Here is a short example showing how to configure a basic CherryPy application as a service in Windows. See the tips and tricks after the code for more information.

"""
The most basic (working) CherryPy 3.0 Windows service possible.
Requires Mark Hammond's pywin32 package.
"""

import cherrypy
import win32serviceutil
import win32service
import win32event

class HelloWorld:
    """ Sample request handler class. """

    def index(self):
        return "Hello world!"
    index.exposed = True


class MyService(win32serviceutil.ServiceFramework):
    """NT Service."""
    
    _svc_name_ = "CherryPyService"
    _svc_display_name_ = "CherryPy Service"

    def __init__(self, args):
        win32serviceutil.ServiceFramework.__init__(self, args)
        # create an event that SvcDoRun can wait on and SvcStop
        # can set.
        self.stop_event = win32event.CreateEvent(None, 0, 0, None)

    def SvcDoRun(self):
        cherrypy.tree.mount(HelloWorld(), '/')
        
        # in practice, you will want to specify a value for
        # server.log_file below or in your config file.  If you
        # use a config file, be sure to use an absolute path to
        # it, as you can't be assured what path your service
        # will run in.
        cherrypy.config.update({
            'global':{
                'autoreload.on': False,
                'server.log_to_screen': False,
                }
            })
        # set init_only=True so that start() does not block
        cherrypy.server.start()
        cherrypy.engine.start(blocking=False)
        # now, block until our event is set...
        win32event.WaitForSingleObject(self.stop_event, win32event.INFINITE)
    
    def SvcStop(self):
        self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)
        cherrypy.server.stop()
        win32event.SetEvent(self.stop_event)

if __name__ == '__main__':
    win32serviceutil.HandleCommandLine(MyService)

Installation

Save this source code into a file called MyService.py and then type:

python MyService.py

You will see a list of options for installing, removing, starting, and stopping your service.

To install your new service type:

python MyService.py install

Then type:

python MyService.py start

to start it. You can also start and stop the service by going to the Start menu, Administrative Tools, Services, and looking for the name of your service.

Running Your CherryPy Application

When you are ready to turn your own CherryPy application into a service, you will probably encounter several things that the simple example above does not.

Working Directory

When your service starts, the working directory is likely to be somewhere different than when you launch your CherryPy application from the command line. You will need to use full path's to configuration files, etc.

Another way around this is to add os.chdir('c:\\path\\to\\CherryPy\\application') just before cherrypy.server.start(). This will change your working directory to the place where your application is installed.

No Autoreloader

The autoloader doesn't play nice as a service. It watches for stuff to change, and then tries to restart the application. Which fails. Make sure you have

[global] 
engine.autoreload.on = False

in your server configuration file.

Debugging a Windows Service

It isn't very easy to debug a windows service. Make sure your application runs from the command line with no problems before spending any time trying to get it to work as a service. If your application works from the command line, but doesn't work as a service, these tips may help you see what is wrong.

Firewalls

Beware of the XP Service Pack 2 firewall. If it is on, it will block programs from listening on ports. When you run your CherryPy application from the command line, it will pop up a window and ask you if you want to grant access to the program python.exe. You say yes, thinking this will work for both the command line and the service. Nope. The service actually runs the executeable pythonservice.exe. If the firewall is blocking that program from opening ports, your service will silently fail to start. This is probably also true for ZoneAlarm, BlackIce Defender, and other firewall programs.

Look in the Event Viewer

Go to the Start Menu, Administrative Tools, Event Viewer, and click on "Applications". Look for events with a source that is the name of your service.

Make sure you have a log file

CherryPy will log stuff to disk if you put the following in your app configuration file:

log.error_file = 'c:\\path\to\logfile'
log.screen = False

Look in the log file and see if anything looks strange.

Log tracebacks

Tracebacks may help you see where your application is failing. Put this in your app config file:

tools.log_tracebacks.on = True

Restart your service, and look in the log file again.

Thanks to Robert Brewer for tips on getting this working and Jared for the thorough documentation.

Hosted by WebFaction

Log in as guest/cherrypy to create/edit wiki pages