| Name | How to run Pylons as a Windows service |
|---|---|
| Space | Pylons CookBook |
| Section | |
| Page | How to run Pylons as a Windows service |
| Version | 1.0 |
| Status | Draft |
| Curator | Graham Higgins |
| Reviewed | False |
| Author(s) |
How to run Pylons as a Windows service
This tutorial will demonstrate how to launch a pylons app as a windows service. Most of the code is taken directly from a CherryPy example I found while trying to figure out how to do this for myself.
The tutorial assumes that:
- you already have a pylons application installed and can be run from the usual command line (paster serve your.ini)
- you have Marks Hammond's pywin32 installed
- If you are running ActiveState's python distribution then it's already installed
1) copy the code below
First you will want to copy the code below to the same folder as your application's ini file as WindowsService.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 | """ The most basic (working) Windows service possible. Requires Mark Hammond's pywin32 package. Most of the code was taken from a CherryPy 2.2 example of how to set up a service """ import pkg_resources import win32serviceutil from paste.script.serve import ServeCommand as Server import os, sys import ConfigParser import win32service import win32event class DefaultSettings(object): def __init__(self): if os.path.dirname(__file__): os.chdir(os.path.dirname(__file__)) # find the ini file self.ini = [x for x in os.listdir('.') if os.path.splitext(x)[1].lower().endswith('ini')] # create a config parser opject and populate it with the ini file c = ConfigParser.SafeConfigParser() c.read(self.ini[0]) self.c = c def getDefaults(self): ''' Check for and get the default settings ''' if ( (not self.c.has_section('winservice')) or (not self.c.has_option('winservice', 'service_name')) or (not self.c.has_option('winservice', 'service_display_name')) or (not self.c.has_option('winservice', 'service_description')) ): print 'setting defaults' self.setDefaults() service_name = self.c.get('winservice', 'service_name') service_display_name = self.c.get('winservice', 'service_display_name') service_description = self.c.get('winservice', 'service_description') iniFile = self.ini[0] return service_name, service_display_name, service_description, iniFile def setDefaults(self): ''' set and add the default setting to the ini file ''' if not self.c.has_section('winservice'): self.c.add_section('winservice') self.c.set('winservice', 'service_name', 'WSCGIService') self.c.set('winservice', 'service_display_name', 'WSCGI windows service') self.c.set('winservice', 'service_description', 'WSCGI windows service') cfg = file(self.ini[0], 'wr') self.c.write(cfg) cfg.close() print ''' you must set the winservice section service_name, service_display_name, and service_description options to define the service in the %s file ''' % self.ini[0] sys.exit() class MyService(win32serviceutil.ServiceFramework): """NT Service.""" d = DefaultSettings() service_name, service_display_name, service_description, iniFile = d.getDefaults() _svc_name_ = service_name _svc_display_name_ = service_display_name _svc_description_ = service_description 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): os.chdir(os.path.dirname(__file__)) s = Server(None) s.run([self.iniFile]) win32event.WaitForSingleObject(self.stop_event, win32event.INFINITE) def SvcStop(self): self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING) #win32event.SetEvent(self.stop_event) self.ReportServiceStatus(win32service.SERVICE_STOPPED) sys.exit() if __name__ == '__main__': win32serviceutil.HandleCommandLine(MyService) |
2) Set up the Windows service
All windows services need to have unique parameters defined so that windows can identify them, such as:
- service_name
- This is the short name that windows uses to manage the service and is used by the net start comment This name must be unique
- service_display_name
- This what is displayed in the list of services as the service name. Typically this is a little more descriptive then the service_name, but they may be the same
- service_description
- this is a short description of what the service does and is displayed along side the service name in the list of services. This is optional and may be left blank
- To setup the Windows service simply run the WindowsService.py program. The program will search for your ini within the directory it is run from, and search for the appropriate "winservice" section. If you have created multiple ini files WindowsService.py simply picks the first one it finds. If the "winservice" section is not found it will be added with the default settings. If this is the first time you've run WindowsService.py I would suggest editing the new section with values which make sence to you.
- Once you have edited winsrvice secion in the ini file, install the service with the following command line:
- WindowsService.py install
- Run the service
- WindowsService.py start
- Running WindowsService.py without any commandline arguments will display a nice help screen with service control options
3) What if something goes wrong?
If something goes wrong and the service does not start take a look at the Application log under the event viewer, that should help you debug what might have gone wrong
If you have any questions, feel free to ask them at: http://groups.google.com/group/pylons-discuss
Jose
Comments (2)
Apr 21, 2008
James Su says:
Thanks! But I don't like "guess", so modified your code to read certain ini file...Thanks!
But I don't like "guess", so modified your code to read certain ini file:
#if os.path.dirname(__file__): #os.chdir(os.path.dirname(__file__)) # find the ini file #self.ini = [x for x in os.listdir('.') #if os.path.splitext(x)[1].lower().endswith('ini')] self.ini = [os.path.join(os.environ['WINDIR'], 'MyApp.ini')]Then you can rename your development.ini or product.ini to MyApp.ini as you like.
Aug 23, 2009
Tibor Arpas says:
This work's very well. I just didn't like the copy & paste approach for ever...This work's very well. I just didn't like the copy & paste approach for every project/every deployment. So I tried to generalize the script and give it the config file parameter. I found out it's not completely straightforward. So I've put up my general script for the others to use. The module is called wsgisvc (http://pypi.python.org/pypi/wsgisvc).
"wsgisvc" replaces "WindowsService.py" and allows you to specify any configuration file you like with the -c option.
etc.. Also the [winservice] options are altered so check out the documentation for wsgisvc if you need a general script.