Page Tools:
Wiki Relationships:
Admin Tools:
CherryPaste with Eggs
Mmmmm, what do I smell cooking? Yes I'll take a little cherry pie. Oh could you top it off with an egg and some glue? Perfect... The aim of this article is to explain how to use CherryPy with Paste and then how to deploy an egg using Paste as well. The article takes a very simple example and goes through the process. These steps took me a while because I wasn't very familiar with Paste or eggs, but now I feel a little more comfortable with them. Since a lot of this knowledge isn't collated into any one place I thought I'd share it here.
Contents |
Why Paste?
One of my pet peeves with Python web frameworks is the issue of deployment. Because there are so many frameworks (you could blame this on python making it so easy to create a framework;) ) and so many different web servers, when you commit to a framework you are limiting yourself to that framework (and the web servers it supports). Yet there are useful tools and apps written in other frameworks. How do you take advantage of these? Paste is an attempt to take the WGSI abstraction (that should help alleviate this issue of framework server impedance mismatch) and make it easy to admin and deploy applications. Ideally using Paste one will soon be able to deploy many different types of WSGI compliant components easily and within the same server.
Install Dependencies
We have a few dependencies that we need in order for everything to work. Luckily there exists Setuptools which allows for really easy installation of packages using eggs (eggs can be though of as analogous to JAR files in Java). We will need to install setuptools, Paste, PasteScript, PasteDeploy, CherryPy, and CherryPaste.
Setuptools is easy to install just download ez_setup.py and run it:
python ez_setup.py
That should add an command, "easy_install" to your machine. Now you should be able to install most of these components doing
easy_install -Z Paste easy_install -Z PasteScript easy_install -Z PasteDeploy easy_install -Z CherryPaste==dev
(Note I like to use the -Z option, so that the egg is unzipped as well. Otherwise the egg will actually be a zip file, which makes browsing the source a little tedious when it is necessary.)
I checked out the development version of CherryPaste. You will also need version 2.2 of CherryPy (I had to check it out from svn and run easy_install on the setup.py file it had):
svn co http://svn.cherrypy.org/trunk/ cherrypy cd cherrypy easy_install -Z .
Modifying the Cherrypy tutorial to run under Paste
For the purposes of this article I'm going to use the tut01_helloworld.py file included in the tutorial directory from the CherryPy distribution.
First lets run that as a CherryPy standalone application to test that CherryPy is working.
cd [directory of cherrypy tutorials] python tut01_helloworld.py
If you were successful in doing this you should be able to go to http://localhost:8080/ and see a very simple website. The console from where you typed this should look something like this:
mharrison[1196] python tut01_helloworld.py 20/Jan/2006:10:46:43 CONFIG INFO Server parameters: 20/Jan/2006:10:46:43 CONFIG INFO server.environment: production 20/Jan/2006:10:46:43 CONFIG INFO server.log_to_screen: True 20/Jan/2006:10:46:43 CONFIG INFO server.log_file: 20/Jan/2006:10:46:43 CONFIG INFO server.log_tracebacks: True 20/Jan/2006:10:46:43 CONFIG INFO server.log_request_headers: False 20/Jan/2006:10:46:43 CONFIG INFO server.protocol_version: HTTP/1.0 20/Jan/2006:10:46:43 CONFIG INFO server.socket_host: 20/Jan/2006:10:46:43 CONFIG INFO server.socket_port: 8080 20/Jan/2006:10:46:43 CONFIG INFO server.socket_file: 20/Jan/2006:10:46:43 CONFIG INFO server.reverse_dns: False 20/Jan/2006:10:46:43 CONFIG INFO server.socket_queue_size: 5 20/Jan/2006:10:46:43 CONFIG INFO server.thread_pool: 10 20/Jan/2006:10:46:43 HTTP INFO Serving HTTP on http://localhost:8080/
Add some Paste in
Ok, now lets see if we can add Paste into this. What value does Paste add? Well, if you are using other apps under Paste, it makes the configuration for deployment identical. Another value is that it should allow you to run multiple applications in the same server. (CherryPy alone doesn't provide this functionality currently). First create a Paste configuration file (named config.ini) like the following:
[app:main] use = egg:CherryPaste root_object = tut01_helloworld:HelloWorld() [server:main] use = egg:Paste#http host = 127.0.0.1 port = 8080
This tells Paste to use CherryPaste for the app we are deploying. For the root object, use an instance of the HelloWorld class found in the tut01_helloworld package.
It also tells Paste that for the main server, listen on the loopback address and serve on port 8080.
To deploy using paste type the following.
mharrison[1226] paster serve config.ini
Simple right? Hmmm, maybe not, mine crashes, complaining that it can't find helloworld.
mharrison[1221] paster serve config.ini
20/Jan/2006:10:54:38 CONFIG INFO Server parameters:
20/Jan/2006:10:54:38 CONFIG INFO server.environment: development
20/Jan/2006:10:54:38 CONFIG INFO server.log_to_screen: True
20/Jan/2006:10:54:38 CONFIG INFO server.log_file:
20/Jan/2006:10:54:38 CONFIG INFO server.log_tracebacks: True
20/Jan/2006:10:54:38 CONFIG INFO server.log_request_headers: True
20/Jan/2006:10:54:38 CONFIG INFO server.protocol_version: HTTP/1.0
20/Jan/2006:10:54:38 CONFIG INFO server.socket_host:
20/Jan/2006:10:54:38 CONFIG INFO server.socket_port: 8080
20/Jan/2006:10:54:38 CONFIG INFO server.socket_file:
20/Jan/2006:10:54:38 CONFIG INFO server.reverse_dns: False
20/Jan/2006:10:54:38 CONFIG INFO server.socket_queue_size: 5
20/Jan/2006:10:54:38 CONFIG INFO server.thread_pool: 0
Traceback (most recent call last):
File "/data1/virtualpython/bin/paster", line 5, in ?
pkg_resources.run_script('PasteScript==0.4.1', 'paster')
File "/data1/virtualpython/lib/python2.3/site-packages/
setuptools-0.6a10dev_r42047-py2.3.egg/pkg_resources.py", line 407, in run_script
self.require(requires)[0].run_script(script_name, ns)
File "/data1/virtualpython/lib/python2.3/site-packages/
setuptools-0.6a10dev_r42047-py2.3.egg/pkg_resources.py", line 920, in run_script
execfile(script_filename, namespace, namespace)
File "/data1/virtualpython/lib/python2.3/site-packages/
PasteScript-0.4.1-py2.3.egg/EGG-INFO/scripts/paster", line 18, in ?
command.run()
File "/data1/virtualpython/lib/python2.3/site-packages/
PasteScript-0.4.1-py2.3.egg/paste/script/command.py", line 67, in run
invoke(command, command_name, options, args[1:])
File "/data1/virtualpython/lib/python2.3/site-packages/
PasteScript-0.4.1-py2.3.egg/paste/script/command.py", line 107, in invoke
exit_code = runner.run(args)
File "/data1/virtualpython/lib/python2.3/site-packages/
PasteScript-0.4.1-py2.3.egg/paste/script/command.py", line 202, in run
result = self.command()
File "/data1/virtualpython/lib/python2.3/site-packages/
PasteScript-0.4.1-py2.3.egg/paste/script/serve.py", line 170, in command
relative_to=base)
File "/data1/virtualpython/lib/python2.3/site-packages/
PasteDeploy-0.4-py2.3.egg/paste/deploy/loadwsgi.py", line 183, in loadapp
return loadobj(APP, uri, name=name, **kw)
File "/data1/virtualpython/lib/python2.3/site-packages/
PasteDeploy-0.4-py2.3.egg/paste/deploy/loadwsgi.py", line 204, in loadobj
return context.create()
File "/data1/virtualpython/lib/python2.3/site-packages/
PasteDeploy-0.4-py2.3.egg/paste/deploy/loadwsgi.py", line 574, in create
return self.object_type.invoke(self)
File "/data1/virtualpython/lib/python2.3/site-packages/
PasteDeploy-0.4-py2.3.egg/paste/deploy/loadwsgi.py", line 93, in invoke
return context.object(context.global_conf, **context.local_conf)
File "/data1/virtualpython/lib/python2.3/site-packages/
CherryPaste-0.0dev_r4526-py2.3.egg/cherrypaste/pastify.py", line 92, in make_app
root_object = import_string.eval_import(root_object)
File "/data1/virtualpython/lib/python2.3/site-packages/
Paste-0.4-py2.3.egg/paste/util/import_string.py", line 20, in eval_import
module = import_module(module_name)
File "/data1/virtualpython/lib/python2.3/site-packages/
Paste-0.4-py2.3.egg/paste/util/import_string.py", line 49, in import_module
mod = __import__(s)
ImportError: No module named helloworld
After some more perusal of the documentation, I ended up going to the Paste mailing list for a solution. Ian Bicking was kind enough to nudge me in the right direction. The python sys.path variable (you can think of this as somewhat analagous to CLASSPATH if you are coming from a Java world) normally contains the local directory, but this in NOT the case when using Paste, the local directory (it shows up as '' when you print sys.path) is removed from sys.path. To adjust for this set PYTHONPATH appropriately (or put helloworld in another directory that sys.path scans for files). Since I'm running the command from the same directory that contains my python code and I'm using bash I do the following:
export PYTHONPATH=.
Now I run the paster command again, and I'm serving up pages using Paste.
mharrison[1229] paster serve config.ini 20/Jan/2006:11:04:19 CONFIG INFO Server parameters: 20/Jan/2006:11:04:19 CONFIG INFO server.environment: development 20/Jan/2006:11:04:19 CONFIG INFO server.log_to_screen: True 20/Jan/2006:11:04:19 CONFIG INFO server.log_file: 20/Jan/2006:11:04:19 CONFIG INFO server.log_tracebacks: True 20/Jan/2006:11:04:19 CONFIG INFO server.log_request_headers: True 20/Jan/2006:11:04:19 CONFIG INFO server.protocol_version: HTTP/1.0 20/Jan/2006:11:04:19 CONFIG INFO server.socket_host: 20/Jan/2006:11:04:19 CONFIG INFO server.socket_port: 8080 20/Jan/2006:11:04:19 CONFIG INFO server.socket_file: 20/Jan/2006:11:04:19 CONFIG INFO server.reverse_dns: False 20/Jan/2006:11:04:19 CONFIG INFO server.socket_queue_size: 5 20/Jan/2006:11:04:19 CONFIG INFO server.thread_pool: 0 Starting server in PID 19902. serving on 127.0.0.1:8080
Stir in some eggs
Now we want to package up our application as an egg and deploy that egg using paste. Why? Those coming from a Java world could think of an egg as analogous to a WAR file. Ie, it's one file that contains everything the app needs to run. How would we do deploy using eggs? The egg documentation is pretty good, but it doesn't give an example. We are in luck though, because Eggs are basically a superset of the standard library distutils. To create an egg, create a setup.py file just like you would do if you were using distutils. And if you browse through the distutils documentation you will find a very simple example of creating a setup.py file. This example is basically all we need to create our egg. My setup.py file looks like this:
from setuptools import setup
setup(name="helloworld",
version="0.1",
py_modules=["tut01_helloworld"]
)
Basically, this simple file says, the name of our package will be helloworld and it includes the tut01_helloworld.py file in it. (I also gave it version information).
To create an egg from this do the following:
python setup.py bdist_egg
This will create a build and a dist. In the dist (distribution) directory should be your newly laid egg. Update your PYTHONPATH so that the directory containing the egg is on it or install the egg like this:
easy_install setup.py
The configuration file also needs to be changed to know about the egg. We need to add a require key to it like this:
[app:main] use = egg:CherryPaste require = helloworld root_object = tut01_helloworld:HelloWorld [server:main] use = egg:Paste#http host = 127.0.0.1 port = 8080
You should be able to use the same paster command and now serve the simple page from an egg.
Conclusion
The purpose of this article is to provide a very walkthrough of using Paste and eggs together. Much thanks to Ian Bicking for his wonderful work in developing and evangelizing paste as well as his patience in answering my questions. Feel free to email Matt (mharrison@spikesource.com) with any questions or suggestions.
Most Recent |
Most Popular |
Most Active Categories |
| Back To Top | Add New Article | Printable Page |

Testing
