CherryPy, Paste and WSGI
CherryPy, like Paste and a slew of other Python web projects, is a good fit for use in web applications built on/from a WSGI stack.
Playing Nice
Let's take a look at how Paste and CherryPy can be combined to piece together the skeleton of a website made from smaller component applications. For a real site, there would need to be plenty of customization beyond the initial WSGI composition, but it is a start.
The Players
- CherryPy 3
- Paste 1.1 (EvalException, URLMap, PasteDeploy and PasteScript)
- WSGIUtils
The Home Team
To start with, we will need a small helper function to make an "app_factory" as defined by the PasteDeploy docs.
We also make sure that cherrypy.engine.start only gets called once. This is probably not the best solution, so if you come up with something better, please share on the cherrypy-users mailing list.
#cpwsgihelper.py import cherrypy from cherrypy._cpengine import STARTED, STARTING, STOPPED # some friendly global config entries cherrypy.config.update({'global':{'request.throw_errors':True, 'log.screen':False, 'engine.autoreload_on':False, } }) def init_wsgi(): """Start the CherryPy engine, but only once, in case there are multiple CP WSGI apps in use in one process. """ if cherrypy.engine.state not in (STARTED, STARTING): cherrypy.engine.start(blocking=False) def make_factory(root): """Return a PasteDeploy compatible app_factory that will configure the given Application root. """ def app_factory(global_config, **local_conf): cherrypy.config.update(global_config) app = cherrypy.Application(root(), script_name=None) app.merge({'/': local_conf}) init_wsgi() return app return app_factory
Now let's create a simple "application" that we will pretend is a blog:
#cp_blog_app.py import cherrypy from cpwsgihelper import make_factory class BlogApp(object): @cherrypy.expose def index(self): return "Blog app index" @cherrypy.expose def foo(self): # this config value comes from the PasteDeply config file return cherrypy.request.config['bar'] @cherrypy.expose def problem(self): assert 0, "Aaaaaahhhhh!" # create an app factory for using the application with Paste Deploy app_factory = make_factory(BlogApp)
Put that file into a folder called "blogapp" or something. The main thing to notice here is that we create a PasteDeploy compatible WSGI app_factory with the make_factory function. Paste is able to call that function with configuration information and get back a configured cherrypy.Application instance.
Now we need a setup script that will generate a setuptools egg for our application. CherryPy makes no assumptions on how you want to deploy your application, so creating the setup.py file is up to you.
Here's a super-simple example:
#setup.py from setuptools import setup setup(name="cp_blog_app", py_modules=["cp_blog_app"], entry_points={"paste.app_factory":["main=cp_blog_app:app_factory"]}, )
The only special thing going on in setup.py is the definition of an "entry point" in the paste.app_factory entry point group. It is basically saying that applications that can make use of paste.app_factory can make use of our application via the "main" entry point. Read that over a few times and peek again at the source if you have to. You can also read more about entry points.
Go ahead and save that file in the same directory as cp_blog_app.py. Then, from a command prompt in that directory, run python setup.py develop. Basically, that will "install" the application to your Python site-packages location linked back to your the source in the current directory. I'm not going into it further - setuptools has completely adequate documentation already ;-)
Checkpoint 1
Let's take stock of what we have accomplished so far:
- We have a module that provides a few utility functions to make working with independent CherryPy WSGI applications a little nicer.
- We have a sweet blog application that we have written and installed as an Egg.
- The blog application is installed with an "entry point" that allows us to easily use it from within PasteDeploy.
The Other Team Steps to the Plate
Ok, let's get some PasteDeploy action going. Save this as simple.conf:
[app:main] use = egg:cp_blog_app#main bar = let's play nice [server:main] use = egg:Paste#http host = 127.0.0.1 port = 80
What we are doing here is telling PasteDeploy that we want to serve a single application from the cp_blog_app with the entry point "main" that we defined earlier. We also set a config value that will get passed along to the application (thanks to our make_factory}} function in {{{cpwsgihelpers). Finally, we define a server to launch that will host the application. Feel free to change the config defaults as necessary.
Let's test out what we've got. From a command prompt, run the following command:
Windows: c:\PythonXX\Scripts\paster serve simple.conf *nix: paster serve simple.conf
If all goes well, that should start a server running on the specified port and you should be able to browse around to the various paths in the application ("/", "/foo" and "/problem"). Go ahead and try it out.
Checkpoint 2
In addition to everything in Checkpoint 1, we now have:
- Our blog app configured by PasteDeploy.
- Out blog app served by Paste's http server and launched via the paster serve command.
Pylons Steps up to the Plate
Pylons is an upcoming Python web framework that lives and breathes WSGI and Paste. Let's see if we can get it to play along too. I'm not going to go into creating and distributing a Pylons app - like setuptools, the documentation is out there if you want to do it yourself.
For a simple Pylons "helloworld" style app, all we need to do is adjust our PasteDeploy config file and allow something else to manage the URL space. We'll let Paste's URLMap handle that.
[composite:main] use = egg:Paste#urlmap / = blogapp /pylongs = pylonsapp [app:blogapp] use = egg:cp_blog_app#main bar = let's play nice [server:main] use = egg:PasteScript#wsgiutils host = 127.0.0.1 port = 80 [app:pylonsapp] use = egg:helloworld#main cache_dir = %(here)s/data session_key = helloworld session_secret = somesecret
There we are. We threw in the WSGIUtils WSGI server there for good measure as well. Run paster serve with your updated config file and you should have both a CherryPy and a Pylons app running in the same process.
Extra Innings
That's about it for the basics. There is a bit more in the archive attached to this wiki page. The source code for these examples plus an extended PasteDeploy config for two CP3 apps, one wrapped with middleware, and the Pylons helloworld app.
Attachments
- CherryPyAndPaste.zip (18.9 kB) -
updated example with changes from #638
, added by dowski on 01/14/07 21:49:55.

