Latest Version: 0.9.6.2
  Dashboard > Pylons Cookbook > ... > Deployment > How to run Pylons as a Windows service
  Pylons Cookbook Log In | Sign Up   View a printable version of the current page.  
  How to run Pylons as a Windows service
Added by Graham Higgins, last edited by Ted Landis on May 09, 2007  (view change) show comment
Labels: 
(None)

Name Space Section Page Version Status Curator Reviewed Author(s)
How to run Pylons as a Windows service Pylons CookBook   How to run Pylons as a Windows service 1.0 Draft Graham Higgins False  

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:

  1. you already have a pylons application installed and can be run from the usual command line (paster serve your.ini)
  2. 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
  1. 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.
  2. Once you have edited winsrvice secion in the ini file, install the service with the following command line:
    • WindowsService.py install
  3. Run the service
    • WindowsService.py start
  4. 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

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.

Posted by James Su at Apr 21, 2008 02:12 | Permalink
Site running on a free Atlassian Confluence Open Source Project License granted to Pylons. Evaluate Confluence today.
Powered by Atlassian Confluence, the Enterprise Wiki. (Version: 2.3.3 Build:#645 Feb 13, 2007) - Bug/feature request - Contact Administrators
Top