"""AppServerService.py
For general notes, see `ThreadedAppServer`.
This version of the app server is a threaded app server that runs as
a Windows NT Service. This means it can be started and stopped from
the Control Panel or from the command line using ``net start`` and
``net stop``, and it can be configured in the Control Panel to
auto-start when the machine boots.
This requires the pywin32__ package to have been installed.
__ http://starship.python.net/crew/mhammond/win32/Downloads.html
To see the options for installing, removing, starting, and stopping
the service, just run this program with no arguments. Typical usage is
to install the service to run under a particular user account and startup
automatically on reboot with::
python AppServerService.py --username mydomain\myusername \
--password mypassword --startup auto install
Then, you can start the service from the Services applet in the Control Panel,
where it will be listed as "WebKit Threaded Application Server". Or, from
the command line, it can be started with either of the following commands::
net start WebKit
python AppServerService.py start
The service can be stopped from the Control Panel or with::
net stop WebKit
python AppServerService.py stop
And finally, to uninstall the service, stop it and then run::
python AppServerService.py remove
You can change several parameters in the top section of this script.
For instance, by changing the serviceName and serviceDisplayName, you
can have several instances of this service running on the same system.
Please note that the AppServer looks for the pid file in the working
directory, so use different working directories for different services.
And of course, you have to adapt the respective AppServer.config files
so that there will be no conflicts in the used ports.
"""
workDir = None
webwareDir = None
libraryDirs = []
runProfile = 0
logFile = 'Logs/webkit.log'
appServer = 'ThreadedAppServer'
serviceName = 'WebKit'
serviceDisplayName = 'WebKit Application Server'
serviceDescription = "This is the threaded application server" \
" that belongs to the WebKit package" \
" of the Webware for Python web framework."
serviceDeps = []
import sys, os, time
import win32service, win32serviceutil
def _dummy_signal(*args, **kwargs):
pass
import signal
signal.signal = _dummy_signal
class AppServerService(win32serviceutil.ServiceFramework):
_svc_name_ = serviceName
_svc_display_name_ = serviceDisplayName
_svc_description_ = serviceDescription
_svc_deps_ = serviceDeps
_workDir = workDir or os.path.dirname(__file__)
_webwareDir = webwareDir
_libraryDirs = libraryDirs
_runProfile = runProfile
_logFile = logFile
_appServer = appServer
def __init__(self, args):
win32serviceutil.ServiceFramework.__init__(self, args)
self._server = None
def SvcStop(self):
self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)
if self._server:
if self._server._running > 2:
self._server.initiateShutdown()
for i in range(30):
if not self._server:
break
time.sleep(0.1)
def SvcDoRun(self):
self._server = log = None
try:
try:
workDir = self._workDir
if not workDir:
workDir = os.path.dirname(__file__)
os.chdir(workDir)
workDir = os.curdir
stdout, stderr = sys.stdout, sys.stderr
logFile = self._logFile
if logFile:
if os.path.exists(logFile):
log = open(logFile, 'a', 1)
log.write('\n' + '-' * 68 + '\n\n')
else:
log = open(logFile, 'w', 1)
else:
log = open('nul', 'w')
sys.stdout = sys.stderr = log
webwareDir = self._webwareDir
if not webwareDir:
webwareDir = os.pardir
global __name__, __package__
__name__ = __name__.split('.')[-1]
__package__ = None
sysPath = sys.path
sys.path = [webwareDir]
from Properties import name as webwareName
from WebKit.Properties import name as webKitName
if webwareName != 'Webware for Python' or webKitName != 'WebKit':
raise ImportError
path = []
webKitDir = os.path.abspath(os.path.join(webwareDir, 'WebKit'))
for p in [workDir, webwareDir] + self._libraryDirs + sysPath:
if not p:
continue
p = os.path.abspath(p)
if p == webKitDir or p in path or not os.path.exists(p):
continue
path.append(p)
sys.path = path
from WebKit import Profiler
Profiler.startTime = time.time()
appServer = self._appServer
appServerModule = __import__('WebKit.' + appServer,
None, None, appServer)
if self._runProfile:
print 'Profiling is on.', \
'See docstring in Profiler.py for more info.'
print
self._server = getattr(appServerModule, appServer)(workDir)
sys.stdout = sys.stderr = log
print
sys.stdout.flush()
if self._runProfile:
from profile import Profile
profiler = Profile()
Profiler.profiler = profiler
sys.stdout.flush()
Profiler.runCall(self._server.mainloop)
else:
self._server.mainloop()
sys.stdout = sys.stderr = log
print
sys.stdout.flush()
if self._server._running:
self._server.initiateShutdown()
self._server._closeThread.join()
if self._runProfile:
print
print 'Writing profile stats to %s...' % Profiler.statsFilename
Profiler.dumpStats()
print 'WARNING: Applications run much slower when profiled,'
print 'so turn off profiling the service when you are done.'
except SystemExit, e:
if log and logFile:
print
errorlevel = e[0]
if errorlevel == 3:
print 'Please switch off AutoReloading in AppServer.Config.'
print 'It does currently not work with AppServerSercive.'
print 'You have to reload the service manually.'
else:
print 'The AppServer has been signaled to terminate.'
print
except Exception, e:
if log and logFile:
print
try:
import traceback
traceback.print_exc(file=sys.stderr)
print 'Service stopped due to above exception.'
except Exception:
print 'ERROR:', e
print 'Cannot print traceback.'
print
raise
except:
raise
finally:
if self._server and self._server._running:
self._server.initiateShutdown()
self._server._closeThread.join()
self._server = None
if log:
sys.stdout, sys.stderr = stdout, stderr
log.close()
def main():
win32serviceutil.HandleCommandLine(AppServerService)
if __name__ == '__main__':
main()