Hi!

After studying
http://wiki.pylonshq.com/display/pylonscookbook/How+to+run+Pylons+as+a+Windows+service

and inspired in the activate_workingenv function found in
http://wiki.pylonshq.com/display/pylonscookbook/mod_wsgi+and+workingenv.py

we finally have a working implementation of a Pylons WindowsService that
works using a virtualenv.

The winservice.ini has an aditional line indicating the virtauil
environment's packages folder

[winservice]
...
virtualenv_package_root = c:\Python25\env-pylons096\Lib\site-packages


The only problem that remains is to "install" many Windows services, one by
ini, following the paste philosophy about
sharing code and starting many instances, each defined by its own ini file.
Our solution (poor man's way) is to have hardcoded in
the service code the used ini. Any help is appreciated

Here is the code of the WindowsService. All the magic about using virtualenv
is in the "activate_virtualenv" function

-------------------------------------

import os, sys
import ConfigParser

class DefaultSettings(object):
    def __init__(self, iniFileName):
        try:
            os.stat(iniFileName)
        except WindowsError, e:
            raise Exception("Create the '%s' file or add the name of the
correct .ini as an extra argument to the commandline." % iniFileName )

        print "Reading the configuration from '%s'." % iniFileName
        self.ini = iniFileName
        # create a config parser opject and populate it with the ini file
        c = ConfigParser.SafeConfigParser()
        c.read(self.ini)
        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')
        virtualenv_package_root = self.c.get('winservice',
'virtualenv_package_root')

        iniFile = self.ini
        return service_name, service_display_name, service_description,
iniFile, virtualenv_package_root

    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, '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
        sys.exit()

inifilename = "winservice.ini"

import pkg_resources
import win32serviceutil

import win32service
import win32event

def activate_virtualenv(package_root):
    import sys
    sys.path.insert(0, package_root)

    real_setuptools = open(os.path.join(package_root,'setuptools.pth
')).read().strip()
    sys.path.insert(0, os.path.join(package_root, real_setuptools))

    # Load all distributions into the working set.
    from pkg_resources import working_set, Environment

    env = Environment(package_root)
    env.scan()

    distributions, errors = working_set.find_plugins(env)
    for dist in distributions:
        working_set.add(dist)

class MyService(win32serviceutil.ServiceFramework):
    """NT Service."""
    fullpath = os.path.realpath(__file__)
    here = os.path.dirname(fullpath)
    os.chdir(here)

    d = DefaultSettings(inifilename)

    service_name, service_display_name, service_description, iniFile,
virtualenv_pkg_root = 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):
        activate_virtualenv(self.virtualenv_pkg_root)

        from paste.script.serve import ServeCommand as Server

        s = Server(None)
        #print "Starting:", s
        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)

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"pylons-discuss" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/pylons-discuss?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to