I plan to rewrite this a bit for Django. I just think it would be
cleaner and logs could be written to file as opposed to stdout. I am not
so familiar with Windows but more Mac and Unix which is reason it would
be nice for someone with Windows to help me out on this. I don't think
it would require too much to provide this functionality. I think in
light of the fact that most people are likely developing on windows
boxes, it would be a plus. I looked at the httpserver code and I don't
think it would much to fit this in.
Regards,
David
From Turbo Gears ...
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)
--
I...@Holsman.net -- blog: http://feh.holsman.net/ -- PH: ++61-3-9877-0909
If everything seems under control, you're not going fast enough. -
Mario Andretti
Regards,
David
Hi David,
I don't use Windows myself, but I could definitely see some use in
this for our friends in the Windows world.
Adrian
--
Adrian Holovaty
holovaty.com | djangoproject.com | chicagocrime.org
Regards,
David
Regards,
David
Would any Windows experts like to take on this project?
Another thought is to not duplicate efforts and but use the cherrypy
wsgi server as the development webserver. This has all the functionality
for django as is and is being actively maintained and developed where
the wsgiref server that is being used now is not. Further it can it
would provide a reliable service for development since it is in fact a
deployable server as it stands.
I have experimented with this in a basic way yesterday since
_cpwsgiserver was specifically written to be adaptable for other
projects. In fact, cherrypy developed their own wrapper for it to
ensure that the core wsgiserver could be used in other projects.
I think this solution is the best. I did not have a problem starting the
service with the wsgiserver but was getting a traceback on urls. Is
there someone that could help me sort this since the issue is with the
app being passed to the wsgiserver since it generates a traceback in the
common middleware as a result. In any case I think this is viable. I
would appreciate some feedback on this or who might be best to perhaps
help me get the request from the middleware all the way through to the
server without trouble.
Further, if cherrypy wsgiserver is used, the cgi for windows service has
already been written and get Django a bit futher along for some sort of
packaging as been suggested for Windows.
Regards,
David
Hi David,
This sounds fine to me. If the license is OK and you put together a
patch, we can take a look and integrate it.
Regards,
David
1. httpserver: Contains app, server, and server wrapper
2. httpctl: Contains controls for start, stop, gracefully restart etc.
Let me know how you feel about possible integration with Django since
the use of the server creates a dependency upon CherryPy. There would be
a need to integrate a development/production server configuration and
modify management for the command line tool.
Regards,
David