<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <html> <head> <link rel="STYLESHEET" href="modpython.css" type='text/css' /> <link rel="first" href="modpython.html" title='Mod_python Manual' /> <link rel='contents' href='contents.html' title="Contents" /> <link rel='index' href='genindex.html' title='Index' /> <link rel='last' href='about.html' title='About this document...' /> <link rel='help' href='about.html' title='About this document...' /> <link rel="next" href="tut-more-complicated.html" /> <link rel="prev" href="tut-overview.html" /> <link rel="parent" href="tutorial.html" /> <link rel="next" href="tut-more-complicated.html" /> <meta name='aesop' content='information' /> <title>3.3 So what Exactly does Mod-python do?</title> </head> <body> <DIV CLASS="navigation"> <div id='top-navigation-panel' xml:id='top-navigation-panel'> <table align="center" width="100%" cellpadding="0" cellspacing="2"> <tr> <td class='online-navigation'><a rel="prev" title="3.2 Quick Overview of" href="tut-overview.html"><img src='previous.png' border='0' height='32' alt='Previous Page' width='32' /></A></td> <td class='online-navigation'><a rel="parent" title="3. Tutorial" href="tutorial.html"><img src='up.png' border='0' height='32' alt='Up One Level' width='32' /></A></td> <td class='online-navigation'><a rel="next" title="3.4 Now something More" href="tut-more-complicated.html"><img src='next.png' border='0' height='32' alt='Next Page' width='32' /></A></td> <td align="center" width="100%">Mod_python Manual</td> <td class='online-navigation'><a rel="contents" title="Table of Contents" href="contents.html"><img src='contents.png' border='0' height='32' alt='Contents' width='32' /></A></td> <td class='online-navigation'><img src='blank.png' border='0' height='32' alt='' width='32' /></td> <td class='online-navigation'><a rel="index" title="Index" href="genindex.html"><img src='index.png' border='0' height='32' alt='Index' width='32' /></A></td> </tr></table> <div class='online-navigation'> <b class="navlabel">Previous:</b> <a class="sectref" rel="prev" href="tut-overview.html">3.2 Quick Overview of</A> <b class="navlabel">Up:</b> <a class="sectref" rel="parent" href="tutorial.html">3. Tutorial</A> <b class="navlabel">Next:</b> <a class="sectref" rel="next" href="tut-more-complicated.html">3.4 Now something More</A> </div> <hr /></div> </DIV> <!--End of Navigation Panel--> <H1><A NAME="SECTION005300000000000000000"></A><A NAME="tut-what-it-do"></A> <BR> 3.3 So what Exactly does Mod-python do? </H1> <P> Let's pretend we have the following configuration: <div class="verbatim"><pre> <Directory /mywebdir> AddHandler mod_python .py PythonHandler myscript PythonDebug On </Directory> </pre></div> <P> <strong>NB:</strong> <span class="file">/mywebdir</span> is an absolute physical path. <P> And let's say that we have a python program (Windows users: substitute forward slashes for backslashes) <span class="file">/mywedir/myscript.py</span> that looks like this: <P> <div class="verbatim"><pre> from mod_python import apache def handler(req): req.content_type = "text/plain" req.write("Hello World!") return apache.OK </pre></div> <P> Here is what's going to happen: The <code>AddHandler</code> directive tells Apache that any request for any file ending with <span class="file">.py</span> in the <span class="file">/mywebdir</span> directory or a subdirectory thereof needs to be processed by mod_python. The "<tt class="samp">PythonHandler myscript</tt>" directive tells mod_python to process the generic handler using the <code>myscript</code> script. The "<tt class="samp">PythonDebug On</tt>" directive instructs mod_python in case of an Python error to send error output to the client (in addition to the logs), very useful during development. <P> When a request comes in, Apache starts stepping through its request processing phases calling handlers in mod_python. The mod_python handlers check whether a directive for that handler was specified in the configuration. (Remember, it acts as a dispatcher.) In our example, no action will be taken by mod_python for all handlers except for the generic handler. When we get to the generic handler, mod_python will notice "<tt class="samp">PythonHandler myscript</tt>" directive and do the following: <P> <OL> <LI>If not already done, prepend the directory in which the <code>PythonHandler</code> directive was found to <code>sys.path</code>. <P> </LI> <LI>Attempt to import a module by name <code>myscript</code>. (Note that if <code>myscript</code> was in a subdirectory of the directory where <code>PythonHandler</code> was specified, then the import would not work because said subdirectory would not be in the <code>sys.path</code>. One way around this is to use package notation, e.g. "<tt class="samp">PythonHandler subdir.myscript</tt>".) <P> </LI> <LI>Look for a function called <code>handler</code> in <code>myscript</code>. <P> </LI> <LI>Call the function, passing it a request object. (More on what a request object is later) <P> </LI> <LI>At this point we're inside the script: <P> <UL> <LI><div class="verbatim"><pre> from mod_python import apache </pre></div> <P> This imports the apache module which provides us the interface to Apache. With a few rare exceptions, every mod_python program will have this line. <P> </LI> <LI><div class="verbatim"><pre> def handler(req): </pre></div> <P> <a id='l2h-23' xml:id='l2h-23'></a> This is our <i class="dfn">handler</i> function declaration. It is called "<tt class="samp">handler</tt>" because mod_python takes the name of the directive, converts it to lower case and removes the word "<tt class="samp">python</tt>". Thus "<tt class="samp">PythonHandler</tt>" becomes "<tt class="samp">handler</tt>". You could name it something else, and specify it explicitly in the directive using "<tt class="samp">::</tt>". For example, if the handler function was called "<tt class="samp">spam</tt>", then the directive would be "<tt class="samp">PythonHandler myscript::spam</tt>". <P> Note that a handler must take one argument - the request object. The request object is an object that provides all of the information about this particular request - such as the IP of client, the headers, the URI, etc. The communication back to the client is also done via the request object, i.e. there is no ``response'' object. <P> </LI> <LI><div class="verbatim"><pre> req.content_type = "text/plain" </pre></div> <P> This sets the content type to "<tt class="samp">text/plain</tt>". The default is usually "<tt class="samp">text/html</tt>", but since our handler doesn't produce any html, "<tt class="samp">text/plain</tt>" is more appropriate. <strong>Important:</strong> you should <strong>always</strong> make sure this is set <strong>before</strong> any call to "<tt class="samp">req.write</tt>". When you first call "<tt class="samp">req.write</tt>", the response HTTP header is sent to the client and all subsequent changes to the content type (or other HTTP headers) are simply lost. <P> </LI> <LI><div class="verbatim"><pre> req.write("Hello World!") </pre></div> <P> This writes the "<tt class="samp">Hello World!</tt>" string to the client. (Did I really have to explain this one?) <P> </LI> <LI><div class="verbatim"><pre> return apache.OK </pre></div> <P> This tells Apache that everything went OK and that the request has been processed. If things did not go OK, that line could be return <tt class="constant">apache.HTTP_INTERNAL_SERVER_ERROR</tt> or return <tt class="constant">apache.HTTP_FORBIDDEN</tt>. When things do not go OK, Apache will log the error and generate an error message for the client. </LI> </UL> </LI> </OL> <P> <strong>Some food for thought:</strong> If you were paying attention, you noticed that the text above didn't specify that in order for the handler code to be executed, the URL needs to refer to <span class="file">myscript.py</span>. The only requirement was that it refers to a <span class="file">.py</span> file. In fact the name of the file doesn't matter, and the file referred to in the URL doesn't have to exist. So, given the above configuration, "<tt class="samp">http://myserver/mywebdir/myscript.py</tt>" and "<tt class="samp">http://myserver/mywebdir/montypython.py</tt>" would give the exact same result. The important thing to understand here is that a handler augments the server behaviour when processing a specific type of file, not an individual file. <P> <em>At this point, if you didn't understand the above paragraph, go back and read it again, until you do.</em> <P> <DIV CLASS="navigation"> <div class='online-navigation'> <p></p><hr /> <table align="center" width="100%" cellpadding="0" cellspacing="2"> <tr> <td class='online-navigation'><a rel="prev" title="3.2 Quick Overview of" href="tut-overview.html"><img src='previous.png' border='0' height='32' alt='Previous Page' width='32' /></A></td> <td class='online-navigation'><a rel="parent" title="3. Tutorial" href="tutorial.html"><img src='up.png' border='0' height='32' alt='Up One Level' width='32' /></A></td> <td class='online-navigation'><a rel="next" title="3.4 Now something More" href="tut-more-complicated.html"><img src='next.png' border='0' height='32' alt='Next Page' width='32' /></A></td> <td align="center" width="100%">Mod_python Manual</td> <td class='online-navigation'><a rel="contents" title="Table of Contents" href="contents.html"><img src='contents.png' border='0' height='32' alt='Contents' width='32' /></A></td> <td class='online-navigation'><img src='blank.png' border='0' height='32' alt='' width='32' /></td> <td class='online-navigation'><a rel="index" title="Index" href="genindex.html"><img src='index.png' border='0' height='32' alt='Index' width='32' /></A></td> </tr></table> <div class='online-navigation'> <b class="navlabel">Previous:</b> <a class="sectref" rel="prev" href="tut-overview.html">3.2 Quick Overview of</A> <b class="navlabel">Up:</b> <a class="sectref" rel="parent" href="tutorial.html">3. Tutorial</A> <b class="navlabel">Next:</b> <a class="sectref" rel="next" href="tut-more-complicated.html">3.4 Now something More</A> </div> </div> <hr /> <span class="release-info">Release 3.3.1, documentation updated on January 29, 2007.</span> </DIV> <!--End of Navigation Panel--> </BODY> </HTML>