Jim Gallacher
jpg at jgassociates.ca
Wed Jun 13 16:15:38 EDT 2007
Hi David, David Bear wrote: > When is the req object made available? > > I'm trying something simple like this. > > import sys > try: > from mod_python import apache > except: > print "import error" > sys.exit(1) > try: > import dummymodule > except: > req.content_type = 'text/plain' > req.write('error importing dummy') > return apache.OK > > when the import dummymodule fails, the req object is not available to > it. Without the req object, how does one send output anywhere? That's a strange bit of code you have there. ;) Your code would only get executed by mod_python once, when the module is first loaded. Read the following treatise and see if things make a bit more sense. The mod_python request object is a pythonic wrapper around the apache request_rec structure and is associated with a *specific* request. It is not a global variable and it's not available outside the context of that request. When apache services a new request it fills out the request_rec data structure (which is a C struct). In the event that mod_python is invoked by a configuration directive (PythonHandler helloworld, for example), apache passes this data structure to mod_python. Mod_python creates a python object, with a number of methods and attributes which allow you to access the contents of the request_rec in a pythonic way. By convention we call this object "req" in the documentation and mailing lists, but the name has no special meaning beyond that. It is not a global variable as your code above would seem to suggest. For the sake of argument, just assume that your code will be read, parsed, compiled and evaluated once when it is first imported. (This is not strictly true, but it's close enough for our purposes here). Code at the module scope will be executed once. So, how do you get at the request object and how is the request processed? Why, through your handler method of course! The request object will be passed as the first parameter to your handler method. Think of the handler method as the entry point into your code for each request. Consider the simplest possible handler as an example: AddHandler mod_python .py PythonHandler helloworld helloworld.py ------------- from mod_python import apache MSG = 'Hello world' my_sum = 10 + 10 def handler(req): req.content_type = 'text/plain' req.write(MSG) return apache.OK Note that the statement my_sum = 10 + 10 is only executed once, not every time a new request arrives. Same for MSG and our initial import statement. The AddHandler directive tells apache that mod_python is going to handle the content generation phase of the request. The PythonHandler directive tells mod_python that the handler is in the helloworld module. Mod_python imports that module if it is not already loaed and looks for a method named "handler", which is the default method name. You can actually specify a different method in your apache configuration: AddHandler mod_python .py PythonHandler helloworld2::alternate_thingy helloworld2.py ------------- from mod_python import apache def handler(req): # This will never be called since we are specifying # a different handler method name in our PythonHandler directive. req.content_type = 'text/plain' req.write('Hello world') return apache.OK def alternate_thingy(req): # this is the handler that will get called. req.content_type = 'text/plain' req.write('Hello world - from the alternate_thingy method') return apache.OK The default method that mod_python will look for depends on the particular directive used (and each directive will get invoked in a different phase the request processing): Configurate Directive Name default mod_python method ---------------------------- --------------------------- PythonPostReadRequestHandler postreadrequesthandler(req) PythonTransHandler transhandler(req) PythonHeaderParserHandler headerparserhandler(req) PythonInitHandler inithandler(req) PythonAccessHandler accesshandler(req) PythonAuthenHandler authenhandler(req) PythonAuthzHandler authzhandler(req) PythonTypeHandler typehandler(req) PythonFixupHandler fixuphandler(req) PythonHandler handler(req) PythonLogHandler loghandler(req) (hint: the method name is a lowercase version of the Directive the "python" prefix stripped off) So what about the Publisher handler? Publisher is an example of a content handler (it's invoked with PythonHandler) that evaluates the request URI and derives the handler method name from that URI. It's dynamically doing what we did with a static directive in the helloworld2 example. Just like any other handler, in any other phase, it calls the method with the request object as the first parameter. I think I know what you're trying to accomplish with your code snippet above, but it really is not the way to go. Trying to make your mod_python code usable (as far as handlers are concerned) outside of mod_python is a loosing proposition. You might want to take a look at the source code and dig into the way we do unit testing. I know it's not as nice as firing up a command line interpreter, but it is possible to write robust code without it. Jim
|