CSC/ECE 517 Fall 2014/ch1a 3 cp: Difference between revisions
(Created page with "'''CherryPy''' CherryPy is an Object-Oriented web framework meant to be Python-like (sparse and clean code). Contents Overview Installation Overview Requirements Installing In...") |
No edit summary |
||
Line 1: | Line 1: | ||
=CherryPy= | |||
CherryPy is an Object-Oriented web framework meant to be Python-like (sparse and clean code). | CherryPy is an Object-Oriented web framework meant to be Python-like (sparse and clean code). | ||
Line 45: | Line 12: | ||
===Overview=== | ===Overview=== | ||
Because CherryPy is nothing more than a Python library, it needs a Python environment (Python 2.3 through to 3.4) and can run on various implementations of Python including IronPython and Jython. [http://docs.cherrypy.org/en/latest/install.html] | Because CherryPy is nothing more than a Python[http://en.wikipedia.org/wiki/Python_(programming_language)] library, it needs a Python environment (Python 2.3 through to 3.4) and can run on various implementations of Python including IronPython and Jython. [http://docs.cherrypy.org/en/latest/install.html] | ||
===Requirements=== | ===Requirements=== | ||
CherryPy requires a Python version between 2.3 and 3.4 inclusively. Certain features require packages but none are mandatory for installation. | CherryPy requires a Python version between 2.3 and 3.4 inclusively. Certain features require packages but none are mandatory for installation.[http://docs.cherrypy.org/en/latest/install.html] | ||
routes for declarative URL mapping dispatcher | *routes[http://routes.readthedocs.org/en/latest/] for declarative URL mapping dispatcher | ||
psycopg2 for PostgreSQL backend session | *psycopg2[http://pythonhosted.org//psycopg2/] for PostgreSQL backend session | ||
pywin32 for Windows services | *pywin32[http://sourceforge.net/projects/pywin32/] for Windows services | ||
python-memcached for memcached backend session | *python-memcached[https://github.com/linsomniac/python-memcached] for memcached backend session | ||
simplejson for a better JSON support | *simplejson[https://github.com/simplejson/simplejson] for a better JSON support | ||
pyOpenSSL if your Python environment does not have the built in ssl module | *pyOpenSSL[https://github.com/pyca/pyopenssl] if your Python environment does not have the built in ssl module | ||
===Installing=== | ===Installing=== | ||
CherryPy can be installed through common Python package managers with the following commands: [http://docs.cherrypy.org/en/latest/install.html] | CherryPy can be installed through common Python package managers with the following commands: [http://docs.cherrypy.org/en/latest/install.html]<br/> | ||
Using setuptools (EasyInstall): | Using setuptools (EasyInstall): | ||
Line 66: | Line 33: | ||
$ pip install cherrypy | $ pip install cherrypy | ||
Installation from yum or apt-get is in the | Installation from yum or apt-get is in the Additional Instructions sections. | ||
Line 74: | Line 41: | ||
===Basic Example=== | ===Basic Example=== | ||
<pre> | |||
#Use the cherrypy python library | |||
import cherrypy | import cherrypy | ||
#Hello World project | |||
class HelloWorld(object): | class HelloWorld(object): | ||
#index page | |||
def index(self): | def index(self): | ||
#Return the page contents | |||
return “Hello World!” | return “Hello World!” | ||
#Allow the page to be visible | |||
index.exposed = True | index.exposed = True | ||
#designates this module as main | |||
if __name__ == ‘__main__’: | if __name__ == ‘__main__’: | ||
#instantiates app and starts server | |||
cherrypy.quickstart(HelloWorld()) | cherrypy.quickstart(HelloWorld()) | ||
/ | </pre> | ||
[http://stackoverflow.com/questions/419163/what-does-if-name-main-do] | [http://stackoverflow.com/questions/419163/what-does-if-name-main-do] | ||
[https://cherrypy.readthedocs.org/en/3.2.6/concepts/basics.html] | [https://cherrypy.readthedocs.org/en/3.2.6/concepts/basics.html] | ||
The above script sets up a basic Hello World application, by defining the index page (http://localhost:8080/) as an object that returns the string “Hello World!”. The page is exposed, meaning that the method can be called to answer a RESTful request. Otherwise, the method is internal only. This is similar to making a method public in Java. [http://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html] | The above script sets up a basic Hello World application, by defining the index page (http://localhost:8080/) as an object that returns the string “Hello World!”. The page is exposed, meaning that the method can be called to answer a RESTful request. Otherwise, the method is internal only. This is similar to making a method public in Java. [http://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html] | ||
===Routing, Parameters, and Exposure=== | ===Routing, Parameters, and Exposure=== | ||
<pre> | |||
#import python library | |||
import cherrypy | import cherrypy | ||
#More Routes application | |||
class MoreRoutes(object): | class MoreRoutes(object): | ||
#Method decorator for index and equates to index.exposed = True | |||
@cherrypy.expose | @cherrypy.expose | ||
def index(self): | def index(self): | ||
return "Hello world!" | return "Hello world!" | ||
#http://localhost:8080/route1 | |||
def route1(self, id=”charles”): | def route1(self, id=”charles”): | ||
#http://localhost:8080/route1?id=somestring | |||
return “Your name is ” + id | return “Your name is ” + id | ||
#Params passed as a GET request. | |||
#Default string is “charles” | |||
route1.exposed = True | route1.exposed = True | ||
#No explicit indication of exposure so calling this route will generate a 404 error | |||
def route2(self): | def route2(self): | ||
return “Still another one” | return “Still another one” | ||
if __name__ == '__main__': | if __name__ == '__main__': | ||
cherrypy.quickstart(MoreRoutes()) | cherrypy.quickstart(MoreRoutes()) | ||
</pre> | |||
/ | |||
The above shows how multiple routes are handled from the Hello World application and the expose decorator. Since route2 is not exposed, the user can not access it and will be shown a 404 HTTP status code (Not Found error). | The above shows how multiple routes are handled from the Hello World application and the expose decorator. Since route2 is not exposed, the user can not access it and will be shown a 404 HTTP status code (Not Found error). | ||
===Multiple Applications=== | ===Multiple Applications=== | ||
<pre> | |||
import cherrypy | import cherrypy | ||
#blog module | |||
class Blog(object): | class Blog(object): | ||
...<blog code>... | ...<blog code>... | ||
#forum module | |||
class Forum(object): | class Forum(object): | ||
...<forum code>... | ...<forum code>... | ||
#”main” method | |||
if __name__ == '__main__': | if __name__ == '__main__': | ||
#designates the blog to be under /blog route | |||
cherrypy.tree.mount(Blog(), ‘/blog’, “blog.conf”) | cherrypy.tree.mount(Blog(), ‘/blog’, “blog.conf”) | ||
#designates the forum to be under /forum route | |||
cherrypy.tree.mount(Forum(), ‘/forum’, “forum.conf”) | cherrypy.tree.mount(Forum(), ‘/forum’, “forum.conf”) | ||
</pre> | |||
[http://docs.cherrypy.org/en/latest/basics.html#multiple-applications] | [http://docs.cherrypy.org/en/latest/basics.html#multiple-applications] | ||
===Database Support=== | ===Database Support=== | ||
CherryPy offers multiple database integration possibilities including | CherryPy offers multiple database integration possibilities including | ||
relational: PostgreSQL, SQLite, MariaDB, Firebird | *relational: PostgreSQL, SQLite, MariaDB, Firebird | ||
column-oriented: HBase, Cassandra | *column-oriented: HBase, Cassandra | ||
key-store: redis, memcached | *key-store: redis, memcached | ||
document oriented: Couchdb, MongoDB | *document oriented: Couchdb, MongoDB | ||
graph-oriented: neo4j | *graph-oriented: neo4j<br/> | ||
Unfortunately, unlike Ruby on Rails, CherryPy does not have a sophisticated “ActiveRecord”-like class for database abstraction, and the database connection has to be established manually. The queries are constructed as static SQL strings with values concatenated during function calls. | Unfortunately, unlike Ruby on Rails, CherryPy does not have a sophisticated “ActiveRecord”-like class for database abstraction, and the database connection has to be established manually. The queries are constructed as static SQL strings with values concatenated during function calls.<br/> | ||
Here is an example of how it would look like | Here is an example of how it would look like | ||
<pre> | |||
# import the Handles | # import the Handles | ||
import MySQLdb | import MySQLdb | ||
import cherrypy | import cherrypy | ||
# defining the connection function | # defining the connection function | ||
def connect(thread_index): | def connect(thread_index): | ||
# Create a connection and store it in the current thread | # Create a connection and store it in the current thread | ||
cherrypy.thread_data.db = MySQLdb.connect('host', 'user', 'password', 'dbname') | cherrypy.thread_data.db = MySQLdb.connect('host', 'user', 'password', 'dbname') | ||
# tell cherrypy to call connect function for each thread | # tell cherrypy to call connect function for each thread | ||
cherrypy.engine.subscribe('start_thread', connect) | cherrypy.engine.subscribe('start_thread', connect) | ||
# example query function | # example query function | ||
def count(val) | def count(val) | ||
c = cherrypy.thread_data.db.cursor() | c = cherrypy.thread_data.db.cursor() | ||
c.execute( 'select count(‘ + val + ’) from table' ) | c.execute( 'select count(‘ + val + ’) from table' ) | ||
res = c.fetchone() | res = c.fetchone() | ||
c.close() | c.close() | ||
return res | return res | ||
</pre> | |||
[http://cherrypy.readthedocs.org/en/latest/tutorials.html#tutorial-9-data-is-all-my-life] | [http://cherrypy.readthedocs.org/en/latest/tutorials.html#tutorial-9-data-is-all-my-life] | ||
==RESTful CherryPy== | ==RESTful CherryPy== | ||
REST (Representational State Transfer) is an abstraction of the architectural elements within a distributed hypermedia system. It ignores the details of component implementation and protocol syntax in order to focus on the roles of components, the constraints upon their interaction with other components, and their interpretation of significant data elements. It encompasses the fundamental constraints upon components, connectors, and data that define the basis of the Web architecture, and thus the essence of its behavior as a network-based application. [http://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm],br/> In othe words, REST is defined by four interface constraints: identification of resources, manipulation of resources through representations, self-descriptive messages, and hypermedia as the engine of application state. [https://cherrypy.readthedocs.org/en/3.2.6/progguide/REST.html] | |||
===Identification of Resources=== | |||
[https://cherrypy.readthedocs.org/en/3.2.6/progguide/REST.html] | |||
===Identification of Resources=== [https://cherrypy.readthedocs.org/en/3.2.6/progguide/REST.html] | Since Cherrypy is an HTTP service provider, resources are referenced by HTTP URIs (Uniform Resource Identifiers), which consist of a scheme, hierarchical identitfier, query, and fragment.<br/> | ||
Since Cherrypy is an HTTP service provider, resources are referenced by HTTP URIs (Uniform Resource Identifiers), which consist of a scheme, hierarchical identitfier, query, and fragment. | *Scheme: in HTTP, the scheme is always http or https. | ||
Scheme: in HTTP, the scheme is always http or https. | *Hierarchical Identifier: consists of an authority and a path (host/port and a path similar to the system file path but not the actual path). The path is mapped to Python Objects via a dispatch mechanism. | ||
Hierarchical Identifier: consists of an authority and a path (host/port and a path similar to the system file path but not the actual path). The path is mapped to Python Objects via a dispatch mechanism. | |||
===Manipulation of Resources Through Representations=== | ===Manipulation of Resources Through Representations=== | ||
[https://cherrypy.readthedocs.org/en/3.2.6/progguide/REST.html] | [https://cherrypy.readthedocs.org/en/3.2.6/progguide/REST.html] | ||
The standard HTTP methods are as follows: | The standard HTTP methods are as follows: | ||
GET retrieves the state of a specific resource | *<code>GET</code> retrieves the state of a specific resource | ||
PUT creates or replaces the state of a specific resource | *<code>PUT</code> creates or replaces the state of a specific resource | ||
POST passes information to a resource to use as it sees fit | *<code>POST</code> passes information to a resource to use as it sees fit | ||
DELETE removes resources | *<code>DELETE</code> removes resources | ||
===Self-Descriptive Messages=== | ===Self-Descriptive Messages=== | ||
Line 224: | Line 177: | ||
===Development=== | ===Development=== | ||
Create an application. Application requirements: | Create an application. Application requirements: | ||
The module needs to define a __main__ | *The module needs to define a <code>__main__ </code> | ||
cherrypy.quickstart(<Application Name>()) for hosting a single application. For example: cherrypy.quickstart(Blog()) | *<code>cherrypy.quickstart(<Application Name>())</code> for hosting a single application. For example: cherrypy.quickstart(Blog()) | ||
cherrypy.tree.mount(<Application Name>(), ‘/<hosting path segment>’, <configuration>) for hosting multiple applications. | *<code>cherrypy.tree.mount(<Application Name>(), ‘/<hosting path segment>’, <configuration>)</code> for hosting multiple applications. For example: <code>cherrypy.tree.mount(Blog(), ‘/blog’, blog_conf) </code> | ||
For example: cherrypy.tree.mount(Blog(), ‘/blog’, blog_conf) | *All parts the users will see must be exposed with either the decorator <code>@cherrypy.expose or attribues exposed = True</code> or <code>route.exposed = True.</code> | ||
All parts the users will see must be exposed with either the decorator @cherrypy.expose or attribues exposed = True or route.exposed = True. | |||
import cherrypy | <pre> | ||
import cherrypy | |||
class HelloWorld(object): | class HelloWorld(object): | ||
def index(self): | def index(self): | ||
return “Hello World!” | return “Hello World!” | ||
index.exposed = True | index.exposed = True | ||
if __name__ == ‘__main__’: | if __name__ == ‘__main__’: | ||
cherrypy.quickstart(HelloWorld()) | cherrypy.quickstart(HelloWorld()) | ||
</pre> | |||
===Deployment=== | ===Deployment=== | ||
Line 249: | Line 202: | ||
==Additional Instructions== | ==Additional Instructions== | ||
Install via yum | ===Install via yum=== | ||
CherryPy is provided by the fedora base repository. In Fedora (and other RPM based Linux distributions, such as CentOS and Red Hat Enterprise Linux): | CherryPy is provided by the fedora base repository. In Fedora (and other RPM based Linux distributions, such as CentOS and Red Hat Enterprise Linux): | ||
$ yum install python-cherrypy | $ yum install python-cherrypy | ||
Install via apt-get [https://cherrypy.readthedocs.org/en/3.2.6/intro/install.html] | ===Install via apt-get=== | ||
[https://cherrypy.readthedocs.org/en/3.2.6/intro/install.html] | |||
CherryPy is also provided in the ubuntu base repository. In Ubuntu (and other Debian-based Linux distributions such as Debian and Mint Linux): | CherryPy is also provided in the ubuntu base repository. In Ubuntu (and other Debian-based Linux distributions such as Debian and Mint Linux): | ||
$ apt-get install python python-dev | $ apt-get install python python-dev | ||
Installation from source | ===Installation from source=== | ||
The source code is hosted on BitBucket and requires Mercurial to pull and install from the site itself. | The source code is hosted on BitBucket and requires Mercurial to pull and install from the site itself. | ||
$ hg clone https://bitbucket.org/cherrypy/cherrypy | $ hg clone https://bitbucket.org/cherrypy/cherrypy | ||
Line 268: | Line 222: | ||
$ python setup.py install | $ python setup.py install | ||
Install for Windows | ===Install for Windows=== | ||
If you are using Windows, install Linux and follow any of the | *If you are using Windows, install Linux and follow any of the a forementioned methods. | ||
If you absolutely must use windows, you can download the .exe file to install CherryPy from here. | *If you absolutely must use windows, you can download the .exe file to install CherryPy from here. | ||
Line 278: | Line 232: | ||
===Server Wide Functions (Plugins)=== | ===Server Wide Functions (Plugins)=== | ||
This type of extension is typically used to provide the application server itself with additional functionality. Such functions are executed with respect to events in the server even when there is no client request processing taking place. | [http://docs.cherrypy.org/en/latest/extend.html#id13] | ||
This type of extension is typically used to provide the application server itself with additional functionality. Such functions are executed with respect to events in the server even when there is no client request processing taking place.<br/> | |||
Typical use case involve | Typical use case involve | ||
Background Tasks (Tasks which involve server mentainance, data management etc. which are independent of user requests) | *Background Tasks (Tasks which involve server mentainance, data management etc. which are independent of user requests) | ||
External Connections (For establishing and maintaining threaded connections to external database or other servers) | *External Connections (For establishing and maintaining threaded connections to external database or other servers) | ||
Delayed/Queued Processing (Cases when certain tasks are required by the user request which take a long time process and the HTTP response should not be blocked.) | *Delayed/Queued Processing (Cases when certain tasks are required by the user request which take a long time process and the HTTP response should not be blocked.)<br/> | ||
These function utilize the Publish-Subscribe Framework implementation of CherryPy. | These function utilize the Publish-Subscribe Framework implementation of CherryPy. Each function subscribes to one or more events on the bus which are published by the CherryPy engine.<br/> The database connection is a good example of such a function<br/> | ||
Each function subscribes to one or more events on the bus which are published by the CherryPy engine. The database connection is a good example of such a function | |||
<pre> | |||
# import the Handles | # import the Handles | ||
import MySQLdb | import MySQLdb | ||
Line 296: | Line 251: | ||
# tell cherrypy to call connect function for each thread | # tell cherrypy to call connect function for each thread | ||
cherrypy.engine.subscribe('start_thread', connect) | cherrypy.engine.subscribe('start_thread', connect) | ||
</pre> | |||
Here the function connect subscribes to the start_thread channel. An event is published on the | Here the function connect subscribes to the <code>start_thread</code> channel. An event is published on the <code>start_thread</code> channel whenever a server thread is started. Here <code>engine</code> is the central bus of the CherryPy server.<br/> | ||
Similarly it is also possible to create new channels and even buses themselves. | Similarly it is also possible to create new channels and even buses themselves. | ||
===Per-Request Functions (Tools)=== | ===Per-Request Functions (Tools)=== | ||
This type of extension is typically used to insert functionality between stages of request processing. Also known as Tools these are simple call-back functions registered with a Hook Point. Hook Points are predefined stages of request processing. CherryPy provides a Default ToolBox containing many tools. Users have the freedom to create their own tools and add them to the default toolbox or create a new one. | [http://docs.cherrypy.org/en/latest/extend.html#per-request-functions] | ||
This type of extension is typically used to insert functionality between stages of request processing. Also known as Tools these are simple call-back functions registered with a Hook Point. Hook Points are predefined stages of request processing. CherryPy provides a Default ToolBox containing many tools. Users have the freedom to create their own tools and add them to the default toolbox or create a new one.<br/> | |||
An example for creating a tool | An example for creating a tool | ||
<pre> | |||
# defining the function to be called | # defining the function to be called | ||
def my_tool(): | def my_tool(): | ||
Line 321: | Line 278: | ||
def index() | def index() | ||
return “Hello World” | return “Hello World” | ||
</pre> | |||
==Watch It In Action== | ==Watch It In Action== | ||
CherryPy is used as a building block for Hulu and Netflix | CherryPy is used as a building block for Hulu[http://tech.hulu.com/blog/2013/03/13/python-and-hulu] and Netflix[http://techblog.netflix.com/2013/03/python-at-netflix.html] |
Revision as of 04:26, 20 September 2014
CherryPy
CherryPy is an Object-Oriented web framework meant to be Python-like (sparse and clean code).
Overview
CherryPy is not a complete stack, such as Ruby on Rails, Laravel, or Django. Complete stack web frameworks offer frontend utilities and storage communications along with other abilities. These aspects that make the frameworks so powerful, however, also contribute to the framework being bulky making development of small web applications such as blogs a bit cumbersome. CherryPy instead prefers to defer decisions such as storage management and interface utilities to the developer [1]
Installation
Overview
Because CherryPy is nothing more than a Python[2] library, it needs a Python environment (Python 2.3 through to 3.4) and can run on various implementations of Python including IronPython and Jython. [3]
Requirements
CherryPy requires a Python version between 2.3 and 3.4 inclusively. Certain features require packages but none are mandatory for installation.[4]
- routes[5] for declarative URL mapping dispatcher
- psycopg2[6] for PostgreSQL backend session
- pywin32[7] for Windows services
- python-memcached[8] for memcached backend session
- simplejson[9] for a better JSON support
- pyOpenSSL[10] if your Python environment does not have the built in ssl module
Installing
CherryPy can be installed through common Python package managers with the following commands: [11]
Using setuptools (EasyInstall):
$ easy_install cherrypy
Using pip
$ pip install cherrypy
Installation from yum or apt-get is in the Additional Instructions sections.
Interface
CherryPy is meant to be pythonic, meaning that development time is meant to be minimized and code is meant to be sparse and clean [12]
Basic Example
#Use the cherrypy python library import cherrypy #Hello World project class HelloWorld(object): #index page def index(self): #Return the page contents return “Hello World!” #Allow the page to be visible index.exposed = True #designates this module as main if __name__ == ‘__main__’: #instantiates app and starts server cherrypy.quickstart(HelloWorld())
The above script sets up a basic Hello World application, by defining the index page (http://localhost:8080/) as an object that returns the string “Hello World!”. The page is exposed, meaning that the method can be called to answer a RESTful request. Otherwise, the method is internal only. This is similar to making a method public in Java. [15]
Routing, Parameters, and Exposure
#import python library import cherrypy #More Routes application class MoreRoutes(object): #Method decorator for index and equates to index.exposed = True @cherrypy.expose def index(self): return "Hello world!" #http://localhost:8080/route1 def route1(self, id=”charles”): #http://localhost:8080/route1?id=somestring return “Your name is ” + id #Params passed as a GET request. #Default string is “charles” route1.exposed = True #No explicit indication of exposure so calling this route will generate a 404 error def route2(self): return “Still another one” if __name__ == '__main__': cherrypy.quickstart(MoreRoutes())
The above shows how multiple routes are handled from the Hello World application and the expose decorator. Since route2 is not exposed, the user can not access it and will be shown a 404 HTTP status code (Not Found error).
Multiple Applications
import cherrypy #blog module class Blog(object): ...<blog code>... #forum module class Forum(object): ...<forum code>... #”main” method if __name__ == '__main__': #designates the blog to be under /blog route cherrypy.tree.mount(Blog(), ‘/blog’, “blog.conf”) #designates the forum to be under /forum route cherrypy.tree.mount(Forum(), ‘/forum’, “forum.conf”)
Database Support
CherryPy offers multiple database integration possibilities including
- relational: PostgreSQL, SQLite, MariaDB, Firebird
- column-oriented: HBase, Cassandra
- key-store: redis, memcached
- document oriented: Couchdb, MongoDB
- graph-oriented: neo4j
Unfortunately, unlike Ruby on Rails, CherryPy does not have a sophisticated “ActiveRecord”-like class for database abstraction, and the database connection has to be established manually. The queries are constructed as static SQL strings with values concatenated during function calls.
Here is an example of how it would look like
# import the Handles import MySQLdb import cherrypy # defining the connection function def connect(thread_index): # Create a connection and store it in the current thread cherrypy.thread_data.db = MySQLdb.connect('host', 'user', 'password', 'dbname') # tell cherrypy to call connect function for each thread cherrypy.engine.subscribe('start_thread', connect) # example query function def count(val) c = cherrypy.thread_data.db.cursor() c.execute( 'select count(‘ + val + ’) from table' ) res = c.fetchone() c.close() return res
RESTful CherryPy
REST (Representational State Transfer) is an abstraction of the architectural elements within a distributed hypermedia system. It ignores the details of component implementation and protocol syntax in order to focus on the roles of components, the constraints upon their interaction with other components, and their interpretation of significant data elements. It encompasses the fundamental constraints upon components, connectors, and data that define the basis of the Web architecture, and thus the essence of its behavior as a network-based application. [18],br/> In othe words, REST is defined by four interface constraints: identification of resources, manipulation of resources through representations, self-descriptive messages, and hypermedia as the engine of application state. [19]
Identification of Resources
[20]
Since Cherrypy is an HTTP service provider, resources are referenced by HTTP URIs (Uniform Resource Identifiers), which consist of a scheme, hierarchical identitfier, query, and fragment.
- Scheme: in HTTP, the scheme is always http or https.
- Hierarchical Identifier: consists of an authority and a path (host/port and a path similar to the system file path but not the actual path). The path is mapped to Python Objects via a dispatch mechanism.
Manipulation of Resources Through Representations
[21] The standard HTTP methods are as follows:
GET
retrieves the state of a specific resourcePUT
creates or replaces the state of a specific resourcePOST
passes information to a resource to use as it sees fitDELETE
removes resources
Self-Descriptive Messages
[22] REST requires messages to be self-descriptive, meaning everything about a message is within the message itself. Such information can be found in the method headers or the definitions of the message’s media type. cherrypy.request.headers and cherrypy.response.headers are used to get this information. Custom-Types are allowed as well.
Hypermedia as the Engine of the Application State
Since REST is stateless and the state is maintained by the application in question, sessions are not maintained by REST, so, by association, CherryPy does not enable sessions by default. However, the REST server helps clients maintain a meaningful state through meaningful URIs
Crash Course
Installation
Install (choose on of the following commands appropriately):
$ easy_install cherrypy $ pip install cherrypy $ yum install python-cherrypy $ apt-get install python python-dev
Development
Create an application. Application requirements:
- The module needs to define a
__main__
cherrypy.quickstart(<Application Name>())
for hosting a single application. For example: cherrypy.quickstart(Blog())cherrypy.tree.mount(<Application Name>(), ‘/<hosting path segment>’, <configuration>)
for hosting multiple applications. For example:cherrypy.tree.mount(Blog(), ‘/blog’, blog_conf)
- All parts the users will see must be exposed with either the decorator
@cherrypy.expose or attribues exposed = True
orroute.exposed = True.
import cherrypy class HelloWorld(object): def index(self): return “Hello World!” index.exposed = True if __name__ == ‘__main__’: cherrypy.quickstart(HelloWorld())
Deployment
The application can be run as a python script in the Python interpreter.
$ python <app file>.py
It will hosted at http://127.0.0.1:8080/ It can also be run as a daemon process with
$cherryd -c <config file> -d -p <PID file>
Additional Instructions
Install via yum
CherryPy is provided by the fedora base repository. In Fedora (and other RPM based Linux distributions, such as CentOS and Red Hat Enterprise Linux): $ yum install python-cherrypy
Install via apt-get
[23] CherryPy is also provided in the ubuntu base repository. In Ubuntu (and other Debian-based Linux distributions such as Debian and Mint Linux):
$ apt-get install python python-dev
Installation from source
The source code is hosted on BitBucket and requires Mercurial to pull and install from the site itself.
$ hg clone https://bitbucket.org/cherrypy/cherrypy $ cd cherrypy $ python setup.py install
Alternatively, the source can be manually downloaded from here in a tarball.
$ tar -xvf CherryPy-#.#.#.tar.gz $ cd CherryPy-#.#.# $ python setup.py install
Install for Windows
- If you are using Windows, install Linux and follow any of the a forementioned methods.
- If you absolutely must use windows, you can download the .exe file to install CherryPy from here.
Extensions
CherryPy provides a flexible open framework. Similar to gems in Rails which add a range of functionality to the framework CherryPy also supports plugins in the the following forms
Server Wide Functions (Plugins)
[24]
This type of extension is typically used to provide the application server itself with additional functionality. Such functions are executed with respect to events in the server even when there is no client request processing taking place.
Typical use case involve
- Background Tasks (Tasks which involve server mentainance, data management etc. which are independent of user requests)
- External Connections (For establishing and maintaining threaded connections to external database or other servers)
- Delayed/Queued Processing (Cases when certain tasks are required by the user request which take a long time process and the HTTP response should not be blocked.)
These function utilize the Publish-Subscribe Framework implementation of CherryPy. Each function subscribes to one or more events on the bus which are published by the CherryPy engine.
The database connection is a good example of such a function
# import the Handles import MySQLdb import cherrypy # defining the connection function def connect(thread_index): # Create a connection and store it in the current thread cherrypy.thread_data.db = MySQLdb.connect('host', 'user', 'password', 'dbname') # tell cherrypy to call connect function for each thread cherrypy.engine.subscribe('start_thread', connect)
Here the function connect subscribes to the start_thread
channel. An event is published on the start_thread
channel whenever a server thread is started. Here engine
is the central bus of the CherryPy server.
Similarly it is also possible to create new channels and even buses themselves.
Per-Request Functions (Tools)
[25]
This type of extension is typically used to insert functionality between stages of request processing. Also known as Tools these are simple call-back functions registered with a Hook Point. Hook Points are predefined stages of request processing. CherryPy provides a Default ToolBox containing many tools. Users have the freedom to create their own tools and add them to the default toolbox or create a new one.
An example for creating a tool
# defining the function to be called def my_tool(): # put tool functunality here print (“Super Amazing Tool”); # creating the decorator for the tool # specifying the hook point and function to be called cherrypy.tools.mytool = cherrypy.Tool(‘on_end_request’, my_tool()) #Sample Usage class Root(object): @cherrypy.expose() @cherrypy.tools.mytool() def index() return “Hello World”
Watch It In Action
CherryPy is used as a building block for Hulu[26] and Netflix[27]