views:

51

answers:

2

I was writing debugging methods for my CherryPy application. The code in question was (very) basically equivalent to this:

import cherrypy

class Page:
    def index(self):
        try:
            self.body += 'okay'
        except AttributeError:
            self.body = 'okay'
        return self.body
    index.exposed = True

cherrypy.quickstart(Page(), config='root.conf')

I was surprised to notice that from request to request, the output of self.body grew. When I visited the page from one client, and then from another concurrently-open client, and then refreshed the browsers for both, the output was an ever-increasing string of "okay"s. In my debugging method, I was also recording user-specific information (i.e. session data) and that, too, showed up in both users' output.

I'm assuming that's because the python module is loaded into working memory instead of being re-run for every request.

My question is this: How does that work? How is it that self.debug is preserved from request to request, but cherrypy.session and cherrypy.response aren't?

And is there any way to set an object attribute that will only be used for the current request? I know I can overwrite self.body per every request, but it seems a little ad-hoc. Is there a standard or built-in way of doing it in CherryPy?

(second question moved to http://stackoverflow.com/questions/3908577/can-i-use-cherrypy-object-attributes-to-cache-the-output-of-a-page)

+2  A: 

You hit the nail on the head with the observation that you're getting the same data from self.body because it's the same in memory of the Python process running CherryPy.

self.debug maintains 'state' for this reason, it's an attribute of the running server.

To set data for the current session, use cherrypy.session['fieldname'] = 'fieldvalue', to get data use cherrypy.session.get('fieldname').

You (the programmer) do not need to know the session ID, cherrypy.session handles that for you -- the session ID is automatically generated on the fly by cherrypy and is persisted by exchanging a cookie between the browser and server on subsequent query/response interactions.

If you don't specify a storage_type for cherrypy.session in your config, it'll be stored in memory (accessible to the server and you), but you can also store the session files on disk if you wish which might be a handy way for you to debug without having to write a bunch of code to dig out session IDs or key/pair values from the running server.

For more info check out http://www.cherrypy.org/wiki/CherryPySessions

synthesizerpatel
I see. I'm trying to understand how self.body stays the same, but cherrypy.session doesn't. (I know *why* it's not intended to, but I'm wondering *how* it works.) Is it simply because the class definition of Session re-defines its own attributes?
willell
It's because cherrypy.session stores a different data collection for each session ID. If you simulate multiple connections from a given session, you should see the data accumulate.
Ryan Ginstrom
+1  A: 

synthesizerpatel's analysis is correct, but if you really want to store some data per request, then store it as an attribute on cherrypy.request, not in the session. The cherrypy.request and .response objects are new for each request, so there's no fear that any of their attributes will persist across requests. That is the canonical way to do it. Just make sure you're not overwriting any of cherrypy's internal attributes! cherrypy.request.body, for example, is already reserved for handing you, say, a POSTed JSON request body.

For all the details of exactly how the scoping works, the best source is the source code.

fumanchu
This is what I was looking for. I had wondered whether I could use cherrypy.request and .response for that, and a canonical method was really what I wanted. Thanks.
willell