Clone wiki

CherryPy / WhatsNewIn21


What's new in CherryPy-2.1

This only discusses new features in 2.1. For a detailed guide on how to upgrade to 2.1, see [wiki:UpgradeTo21].

New config system

The config options are now stored in a dictionary called "cherrypy.config.configMap". It's a dictionary of dictionaries. The keys of the first dictionaries correspond to the PATH of the HTTP requests (except 'global', which is the default). This way you can use different configurations for different PATHs. The default value is:

cherrypy.config.configMap = {
        'global': {
            'server.socketPort': 8080,
            'server.socketHost': '',
            'server.socketFile': '',
            'server.socketQueueSize': 5,

            'server.protocolVersion': 'HTTP/1.0',
            'server.logToScreen': True,
            'server.logFile': '',
            'server.reverseDNS': False,
            'server.threadPool': 0,
            'server.environment': 'development',

To update this dictionary, users should call cherrypy.config.update, either by passing an update dictionary, like this:

    'global': {
        'sessionFilter.on': True,
        'sessionFilter.storageType': 'file'}
# or the shortcut version for 'global':
cherrypy.config.update({'sessionFilter.on': True})

Or by passing a file name, in which case !CherryPy will parse the INI file (see below for more on this format) and store the values in cherrypy.config.configMap, like this:

cherrypy.config.update(file = 'server.cfg')

'''Note that !CherryPy uses "unrepr" to parse the values in your config file, so you need to write them as python expressions (ex: "string", True, 1)'''

'''Also note that the config file keys are now CASE-SENSITIVE'''

To access a config option from your code, the new API is:

cherrypy.config.get(key, defaultValue = None)


cherrypy.config.get('server.socketPort', 8080)

New way of using filters

It is now much easier to use standard filters. No more _cpFilterList is required (although you still have to use it if you want to use some non-standard filter). Standard filters are now included in 2 internal lists called _cpDefaultInputFilterList and _cpDefaultOutputFilterList. All you have to do is enable them through the config file. For instance, if you want to enable EncodingFilter (using utf-8) on all the site and DecodingFilter for everything under /dir1 (using latin-1), all you have to do is put this in your config file:

encodingFilter.on = True

decodingFilter.on = True
decodingFilter.encoding = "latin-1"

The "standard" filters are currently: baseurlfilter, cachefilter, decodingfilter, encodingfilter, gzipfilter, logdebuginfofilter, staticfilter, tidyfilter, virtualhostfilter, xmlrpcfilter

It is also possible to add your own filters like this (since rev 522, you must use [global], not [/]):

#specify where to look for filters
server.filtersRoot = ['.', 'my/filters']

# defines what filters to load for working on the incoming request
# the key is the Python module name without the .py extension
# the value is the classname within that module
server.inputFiltersDict = {'myFilter': 'MyFilterClassIn'}
server.outputFiltersDict = {'myFilter': 'MyFilterClassOut'}

# Now we can work on our filter as with the standard filters
myFilter.on = True
myFilter.saySome = ' world'

myFilter.on = False

From within your filter classes, you will have to call for instance:

cherrypy.config.get('myFilter.on', False)
cherrypy.config.get('myFilter.saySome', '')

New session filter

Sessions have been moved into a filter called "sessionFilter". Sessions are enabled by setting "sessionFilter.on" to True. This gives you access to a dictionary-like object called "cherrypy.session". See the [ Session chapter] of the !CherryPy book for more information about the session system.

New "server.environment" config option

Its value can be "development", "staging" or "production". The default value is "development". Here is what happens for the different values:

  • "development":
  • logDebugInfoFilter is enabled by default
  • the default _cpOnError displays tracebacks in the browser if errors occur but still returns a "200" status code
  • autoreload is enabled by default
  • "production":
  • logDebugInfoFilter is disabled by default
  • the default _cpOnError returns "304" or "500" status codes if errors occur (coming soon)
  • "staging":
  • same as "production" for now


During development, changes made to your code will be reflected on the site instantly! No need to manually stop and restart CherryPy anymore.

New file upload behavior

New HTTP servers, and WSGI support

New Profiler module

CherryPy 2.1 has a new profiler module. "Profiling" is a technique to improve your application by examining the time spent in each (Python) function. The CherryPy profiler module does three things:

1. Collects profiling data for requests

You can easily enable profiling per HTTP-request in the config:

profiling.on: True
profiling.path: "/path/to/profile/dir"

When enabled, the profiler collects timing data. For each HTTP request, it creates a new file in the folder you specify. If you do not specify a path, profiling data is placed in cherrypy/lib/profile. The path you specify must be an absolute path. Each new request is given a filename with an incrementing number: the first file is named "", the second, "", and so on.

Whenever you restart the CP process, the numbering will start again at 0001, and new profiling data will overwrite the old data. Be aware that CherryPy 2.1's autoreloader module may restart your process unexpectedly; set the config value "server.environment" to "production" to disable the autoreloader.

In addition, it is important that you understand exactly what function calls are being examined. The profiling process must begin and end at some point; when you use the built-in profiling functionality, this does not include the time spent by the HTTP server in I/O processes, in request handling before passing control to CherryPy, or in response handling after CherryPy has finished producing output. In addition, HTTP/1.1 requests which are served using generators (with the "yield" statement) will not collect timing information for those generator functions (they are resolved outside of the CherryPy request, in the HTTP server or gateway).

Finally, you should also be aware that the test suite included with CherryPy 2.1 collects profiling data by default. If you've never turned on the profiler, but find files in cherrypy/lib/profile, they may have been generated from a run of the test suite.

2. Shows profiling data in your browser

Once you have finished collecting profiling data, you ''may'' use the hotshot module, provided by Python, to examine and analyze it. However, that takes a bit of setup each time. For quick analysis, the CherryPy profiler module can format your data and show it to you in a browser. Simply execute cherrypy/lib/ as a script, and it will begin serving profiling data on port 8080 by default.

If you set a profiling.path when collecting data, you need to provide that same path to the script as a command arg. For example, if you set profiling.path to "/var/www/myapp/profile", you should execute the profiler script as:

python /var/www/myapp/profile 8000

As you can see, you may also specify a port other than 8080 in the second arg.

Then, point your browser to http://localhost:8080. You'll be served a frameset, with a sidebar to navigate between profiling results (files), and a main frame to show you those results. Results are displayed in 'cumulative' order; that is, the functions which took the most time (including any calls ''they'' made) are displayed at the top of the list. The 'cum' column shows you these times. The 'time' column shows you the time each function took, ''without'' including the time any sub-functions took.

3. Offers generic profiling services

The profiler module is designed to be used in other parts of your application, should you desire it. In general, you should import the module and create a Profiler object as needed, then use the "run" method of that Profiler object. Example:

from cherrypy.lib import profiler

class Root:
    p = profiler.Profiler("/path/to/profile/dir")
    def index(self): = True
    def _index(self):
        return "Hello, world!"

cherrypy.root = Root()

It's not limited to CherryPy page handlers! Use it for any process for which you want to show profiling results in your browser. Here's an example which tests multiple CP requests; the CP core is so fast, even the slow functions complete in less than a hundredth of a second--this aggregates 100 requests to produce more meaningful times:

import cherrypy
from cherrypy.lib import profiler

class HelloWorld:
    def index(self):
        return "Hello world!" = True

cherrypy.root = HelloWorld()
conf = {'server.logToScreen': False,
        'server.environment': 'production',
cherrypy.config.update({'global': conf})

HOST = ""
PORT = 8000

def run_requests():
    for x in xrange(100):
        cherrypy.server.request(HOST, HOST, "GET / HTTP/1.0",
                                [("Host", "%s:%s" % (HOST, PORT))],
                                "", "http")

if __name__ == "__main__":
    p = profiler.Profiler()

New, reusable test suite

The test suite for !CherryPy 2.1 has been greatly improved. There are '''many''' new tests for both basic and advanced functionality. There are new command-line options to control which tests are run, and the output they produce. There are new debugging tools specifically for web page tests. Finally, many of the test suite components are reusable by your applications, so you can start developing your own !CherryPy applications using all of these benefits. See wiki:Testing for more information.