Author: | Dave Kuhlman |
---|---|
Address: | dkuhlman@rexx.com http://www.rexx.com/~dkuhlman |
Revision: | 1.1d |
Date: | Jan. 21, 2004 |
Copyright: | Copyright (c) 2004 Dave Kuhlman. This documentation is covered by The MIT License: http://www.opensource.org/licenses/mit-license. |
Abstract
Documentation on how to set up Quixote with Medusa.
Medusa is a 'server platform' -- it provides a framework for implementing asynchronous socket-based servers (TCP/IP and on Unix, Unix domain, sockets).
For our purposes, Medusa provides an HTTP 1.1 Web server.
This document explains how to use Medusa in support of Quixote.
Down-load Medusa from http://www.amk.ca/python/code/medusa.html.
Unroll it with something like:
tar xvzf medusa-0.5.4.tar.gz
Install Medusa with the following (You may have to become root to do this.):
cd medusa-0.5.4 python setup.py install
Here is a sample, taken from qxdemo, the Quixote demo application:
#!/usr/bin/env python try: from medusa import http_server, xmlrpc_handler except ImportError: print '\n' + '='*50 print 'medusa/ package not found; fetch it from ' print ' http://www.amk.ca/files/python/' print 'and install it.' print '='*50 raise import asyncore from quixote.publish import Publisher from quixote.server import medusa_http from quixote import enable_ptl enable_ptl() # Server that exposes the links demo program on port 8080 PORT = 8080 # [1] print 'Now serving the qxdemo.links demo on port %i' % PORT server = http_server.http_server('', PORT) publisher = Publisher('qxdemo.ui.links') # [2] publisher.config.debug_log = "/tmp/debug" # [3] publisher.config.error_log = "/tmp/error" publisher.setup_logs() dh = medusa_http.QuixoteHandler(publisher, 'qxdemo/links server', server) # [4] server.install_handler(dh) try: asyncore.loop() except KeyboardInterrupt: # [5] pass
Notes and customization (see [n] comments in the code):
Change the port that you want to receive requests on.
Change the Python path to your application. If the root of your application is in a __init__.py file, specify the path to the directory (package) that contains it, for example:
publisher = Publisher('qxdemo.ui')
If the root of your application is in a plain Python source file such as qxdemo/ui/links.py, specify the path to that module, for example:
publisher = Publisher('qxdemo.ui.links')
You can also specify log files (and a lot more) in a Quixote configuration file. In order to do so:
Copy the default configuration script config.py from the Quixote distribution to a location of your choice.
Edit your copy of the configuration file. The default configuration script contains comments to help with this task.
Replace the lines containing publisher.config. ... with the following line containing the path to your configuration script:
publisher.read_config('myconfig.py')
Change the server name string. In our sample script above, the value of the SERVER_SOFTWARE environment variable will be "qxdemo/links server".
The try:except: block enables us to catch a break (Ctrl-C) and perform any needed clean-up. For example, had we subclassed the Publisher class and created any connections, proxies, etc, this would allow us to close connections etc.
Note: You will need to add the directory containing your application to your PYTHONPATH before running the following code.
In order to start your server, run your driver script. For example, if the name of your driver script is server-medusa.py, the following will start your server:
python server-medusa.py
In some applications it is useful to create and reuse things like database connections, proxies for XML-RPC and SOAP client access, etc. Here is a more extensive Medusa driver script that shows how to do this:
#!/usr/bin/env python # # Medusa server that exposes the skeleton program. # from optparse import OptionParser try: from medusa import http_server, xmlrpc_handler except ImportError: print '\n' + '='*50 print 'medusa/ package not found; fetch it from ' print ' http://www.amk.ca/files/python/' print 'and install it.' print '='*50 raise import asyncore from quixote.publish import Publisher from quixote.server import medusa_http from pyPgSQL import PgSQL import xmlrpclib from quixote import enable_ptl enable_ptl() # Warning: Must import SOAPpy *after* enable_ptl. I don't know why. from SOAPpy import SOAPProxy # Default port to listen on. PORT = 8080 CONNECT_ARGS_FILE = 'connection_args.txt' # # A container for persistent connections etc. # class PersistentContainer: pass class MyPublisher(Publisher): def __init__(self, root_namespace, config=None): Publisher.__init__(self, root_namespace, config) self.container = PersistentContainer() connectionFile = file(CONNECT_ARGS_FILE, 'r') connectionArgs = connectionFile.read().strip() connectionFile.close() self.container.dbConnection = PgSQL.connect(connectionArgs) self.container.xmlrpcProxy = xmlrpclib.ServerProxy('http://localhost:8082') self.container.soapProxy = SOAPProxy(str("http://localhost:8083/")) meerkatURI = "http://www.oreillynet.com/meerkat/xml-rpc/server.php" self.container.meerkatServer = xmlrpclib.Server(meerkatURI) def cleanup(self): self.container.dbConnection.close() def start_request(self, request): Publisher.start_request(self, request) request.container = self.container def start_server(port): print 'Now serving the skeleton services on port %i' % port server = http_server.http_server('', port) publisher = MyPublisher('skeleton.ui') publisher.read_config('config.py') publisher.setup_logs() dh = medusa_http.QuixoteHandler(publisher, 'skeleton/services on medusa server', server) server.install_handler(dh) try: asyncore.loop() except KeyboardInterrupt: publisher.cleanup() USAGE_TEXT = """ python %prog [options] example: python %prog -p 8081""" def usage(parser): parser.print_help() sys.exit(-1) def main(): global Verbose parser = OptionParser(USAGE_TEXT) parser.add_option("-p", "--port", type="int", dest="port", help="port to listen on") (options, args) = parser.parse_args() port = PORT if options.port: port = options.port if len(args) == 0: start_server(port) else: usage(parser) if __name__ == "__main__": main()
Explanation:
ReusingConnections: The Quixote Wiki section ReusingConnections describes start-up scripts, how to reuse resources, and how to clean-up resources and connections when the server shuts down.