This page describes the steps needed to run a TurboGears application as a Windows service.
The win32all package (download) must be installed before the Windows service functionality can be used.
Copy the code at the end of this page and create a file called 'service.py' with its contents.
Note: this file does not have to be in the same directory as the TG application code.
Edit service.py's "USER EDIT SECTION" with the appropriate information. A description of each variable follows:
Open a command prompt and navigate to the directory where service.py is located. Use the following commands to install/start/stop/remove your service:
service.py (Lists all available options) service.py install (Installs the service with a manual startup ) service.py --startup auto install (Installs the service with auto startup) service.py start (Starts the service) service.py stop (Stops the service) service.py remove (Removes the service)
The instance's SvcRun() method failed File "C:\Python24\lib\site-packages\win32\lib\win32serviceutil.py", line 742, in SvcRun self.SvcDoRun() File "C:\Documents and Settings\<user>\Desktop\service.py", line 80, in SvcDoRun self.tg_init() File "C:\Documents and Settings\<user>\Desktop\service.py", line 115, in tg_init print 'try to crash the buffer over and over again...' exceptions.IOError: (9, 'Bad file descriptor')
The Cherrpy site also lists a similar method of creating a Cherrypy Windows service.
Use the Windows Event Viewer, the stdout, and the stderr log files to locate problems with your application.
# File name: service.py # # The service module defines a single class (TGWindowsService) that contains # all of the necessary functionality for running a TurboGears application as # a Windows Service. # # To use this class, users must do the following: # 1. Download and install the win32all package # (http://starship.python.net/crew/mhammond/win32/) # 2. Edit the "USER EDIT SECTION with the proper information. # 3. Open a command prompt and navigate to the directory where this file # is located. Use one of the following commands to # install/start/stop/remove the service: # > service.py install # > service.py start # > service.py stop # > service.py remove # Additionally, typing "service.py" will present the user with all of the # available options. # # Once installed, the service will be accessible through the Services # management console just like any other Windows Service. All exceptions # encountered by the TGWindowsService class will be viewable in the # Windows event viewer; all application specific exceptions should appear # in the stdout/stderr logs. # # This module has been tested on Windows Server 2000, 2003, and Windows # XP Professional. # # Note 1: This file does not need to exist in the same directory as the code for # the TurbGears application. The TGWindowsService class will find the # application's code using the "code_dir" class attribute as defined # by the user. # # Note 2: The cherrypy autoreload functionality will not function when cherrypy # is run as a Windows service, so the TGWindowsService class will automatically # disable autoreloading before starting the server. import cherrypy import pkg_resources pkg_resources.require("TurboGears") import sys import os from os.path import * import win32serviceutil import win32service from win32com.client import constants class TGWindowsService(win32serviceutil.ServiceFramework): """TurboGears Windows Service helper class. The TGWindowsService class contains all the functionality required for running a TurboGears application as a Windows Service. The only user edits required for this class are located in the following class variables: _svc_name_: The name of the service (used in the Windows registry). _svc_display_name_: The name that will appear in the Windows Service Manager. code_dir: The full path to the base directory of the user's TG app code (usually where <project_name>-start.py and the *.cfg files are located). root_class: The fully qualified Root class name (e.g. wiki20.controllers.Root) log_dir: The desired location of the stdout and stderr log files. For information on installing the application, please refer to the documentation at the end of this module or navigate to the directory where this module is located and type "service.py" from the command prompt. """ # -- START USER EDIT SECTION # -- Users must edit this section before installing the service. _svc_name_ = '' # (Required) The name of the service. _svc_display_name_ = '' # (Required) The Service Manager display name. code_dir = r'' # (Required) The base directory of the TG app code. root_class = '' # (Required) The fully qualified Root class name. log_dir = r'' # (Optional) The log directory. Default = code_dir. # -- END USER EDIT SECTION def SvcDoRun(self): """ Called when the Windows Service runs. """ self.ReportServiceStatus(win32service.SERVICE_START_PENDING) self.tg_init() cherrypy.root = self.root() self.ReportServiceStatus(win32service.SERVICE_RUNNING) cherrypy.server.start() def SvcStop(self): """Called when Windows receives a service stop request.""" self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING) cherrypy.server.stop() self.ReportServiceStatus(win32service.SERVICE_STOPPED) def tg_init(self): """ Checks for the required data and initializes the application. """ if TGWindowsService.code_dir: os.chdir(TGWindowsService.code_dir) sys.path.append(TGWindowsService.code_dir) # Redirect stdout and stderr to avoid buffer crashes. sys.stdout = open(join(TGWindowsService.log_dir, 'stdout.log'),'a') sys.stderr = open(join(TGWindowsService.log_dir, 'stderr.log'),'a') else: raise ValueError("""The code directory setting is missing. The Windows Service will not run without this setting.""") if not TGWindowsService.root_class: raise ValueError("""The fully qualified root class name must be provided.""") if not TGWindowsService.log_dir: TGWindowsService.log_dir = '.' if exists(join(TGWindowsService.code_dir, "setup.py")): cherrypy.config.update(file="dev.cfg") else: cherrypy.config.update(file="prod.cfg") # Set environment to production to disable auto-reload. cherrypy.config.update({'global': {'server.environment': 'production'},}) # Parse out the root class information and set it to self.root full_class_name = TGWindowsService.root_class last_mark = full_class_name.rfind('.') if (last_mark < 1) or (last_mark + 1) == len(full_class_name): raise ValueError("""The user-defined class name is invalid. Please make sure to include a fully qualified class name for the root_class value (e.g. wiki20.controllers.Root).""") package_name = full_class_name[:last_mark] class_name = full_class_name[last_mark+1:] exec('from %s import %s as Root' % (package_name, class_name)) self.root = Root if __name__ == '__main__': # The following are the most common command-line arguments that are used # with this module: # service.py install (Installs the service with manual startup) # service.py --startup auto install (Installs the service with auto startup) # service.py start (Starts the service) # service.py stop (Stops the service) # service.py remove (Removes the service) # # For a full list of arguments, simply type "service.py". win32serviceutil.HandleCommandLine(TGWindowsService)