| Developer: Open Source
Build a Rapid Web Development Environment for Python Server Pages and Oracle
by Przemyslaw Piotrowski
Get into high-level Web programming with the reliable Oracle Database 10g, scalable Apache Web server, and intuitive, object-oriented Python programming language.
Published July 2006
Developers today benefit from a range of server-side technologies that function as the middle layer between a Web server and the database, including JavaServer Pages (JSP), Active Server Pages (ASP), PHP, and if you're an Oracle developer, PL/SQL Server Pages.
When I was introduced to Python programming language back in 2003, I was amazed by its elegance and ease of use. It is so high level that it writes almost like plain English, looking like pseudocode to unaware programmers. The dynamic nature of Python lets you write a minimum of unambiguous code to accomplish even the most complex tasks.
In this article I will outline an easy method of creating a complete Python Server Pages/Oracle Database 10g rapid Web development environment. I will assume you have none of the components installed on your Windows or Linux system. (If you do, however, you will need to skip some steps accordingly.) All of the featured components are free to download and carry no licensing costs.
Python and Python Server Pages Background
Python offers strong introspection capabilities, dynamic typing, complete object-orientation, extensibility, and platform independence (Windows, Linux, Solaris, Mac OS, Nokia / S60, Pocket PC, and counting). It allows you to be highly productive and results-oriented, focusing on solving problems rather than coping with language-intrinsic features. Python is extremely readable and easy to maintain by putting certain requirements on the code style. I have many Python one-liners (sometimes two-liners if they include the import statement) that actually perform complex tasks, and these are not just "hello-worlders."
One of Python's greatest strengths is its extensive standard library, which provides an out-of-the-box set of modules for most programming tasks (Python programmers refer to it as the "batteries-included strategy") including file I/O, system interaction, networking, data parsing and manipulation, threading, profiling, unit-testing, introspection, XML processing, and many more.
You'll be amazed by the speed of development with Python--you can finally engage the computer to understand what you want to do, not the opposite. You can also use the built-in docstrings -- in-line help strings -- to enable other programmers quickly grasp the idea behind your class or function. (Creating a documentation from the source code is a snap.) For these reasons, Google and NASA are big Python shops, and Microsoft is developing its own version of Python on the .NET platform called IronPython.
Python Server Pages (PSP) are to Python what JavaServer Pages are to Java. Pages rendered with PSP can perform 50 times better than those served with regular CGI processing. Mod_python includes a range of specialized modules that make Web development much easier.
The complete Web development environment must consist of at least three essential components: the Web server, database, and server-side backend technology. There are also functional requirements like reliability, scalability, and interoperability. To address them I have chosen Apache HTTP Server 2.0, Oracle Database 10g Express Edition (XE), and Python 2.4 (with mod_python and cx_Oracle modules). (Read on to find the reasoning behind these choices.)
Windows users will certainly take advantage of "Click Next" installations of all these components, although Linux users still won't be required to type much. I've simplified the installation procedure to make use of the available binaries.
Oracle Database 10g Express Edition
In February 2006, Oracle announced the production release of Oracle Database XE. It is an entry-level, small-footprint version of Oracle Database 10g Release 2 and is completely free to develop, deploy, and distribute.
Available for Windows and Linux operating systems, Oracle Database XE is an excellent choice for PHP, Java, or .NET developers. Furthermore, with the great amount of available third-party modules and drivers, it can be accessed from a range of different programming languages, including Python.
Oracle Database XE comes in two flavors, Western European and Universal. The former includes support only for LATIN1 characters while the latter's default charset is AL32UTF8. The Universal version also includes administrative interfaces translated into Brazilian Portuguese, Chinese (Simplified and Traditional), English, French, German, Italian, Japanese, Korean, and Spanish. Since nobody wants to be explicitly limited to LATIN1, I recommend installing and using the Universal version.
Installing and Running Oracle Database XE
Download OracleXEUniv.exe for Windows or oracle-xe-univ-10.2.0.1-1.0.i386.rpm for RPM-based Linux distributions. (Oracle Database XE is available for Debian as well, but I will not cover it in this document.)
You can now log in to XE's graphical administrative interface by opening http://127.0.0.1:8080/apex/ in your browser. (If the database was configured using custom parameters, change the path appropriately.)
Installing Apache HTTP Server 2.0
Apache HTTP Server is currently deployed on at least two-thirds world's Web servers, according to the latest Netcraft statistics. Enabling even the most scalable architectures, it is available for a choice of system platforms, including Microsoft Windows and Linux.
Apache is however much more than just a Web server. Apache Software Foundation provides support for many open-source, enterprise-grade products, including the famous Struts framework, Tomcat servlet container, Derby database, Axis platform, FOP processor, and Xerces parser, to name just a few. Apache HTTP Server is quite easy to configure and provides unmatched flexibility for various server-side configurations. It also serves as the heart of Oracle HTTP Server, as you may already know.On Windows:
On Linux (RPM method):
To check whether Apache HTTP server is working properly, go to http://127.0.0.1/ and see if the default welcome page shows up.
The configuration of Apache is incomplete, however—you still need to install Python and mod_python. Follow the steps below to complete the installation of the Python interpreter on your operating system.
Linux installation of Python depends completely on the system distribution. There are wide installation choices and the chances that you are already running Python 2.4 are very high if your system is not that old. Visit http://www.python.org/download/linux/ to see the available choices.
We will connect Python to Apache HTTP Server using mod_python, module originally written by Gregory Trubetskoy and generously donated to the Apache Software Foundation. This module has been available on the Internet since 2000, and became part of Apache modules collection in 2002.
Mod_python gives you access to many low-level Apache internals and provides unrivalled flexibility compared to other server-side, Apache-based solutions (like mod_php or mod_perl). You may or may not use these internals, but since we'd like to focus on rapid web development, I will describe the high-level interface it provides, focusing precisely on PSP.
With mod_python you can take the full advantage of Python and its modules, writing server pages that can be cached and wrapped in reusable templates. Please note that the PSP engine is one of many interpreters mod_python provides, but since we would like to embed Python code directly in the page source, PSP is the preferred solution.
Configuring Apache HTTP Server to Handle PSP
After mod_python installation you must make Apache aware of it. For this purpose open APACHE_HOME/conf/httpd.conf for editing(for default Linux location of httpd.conf, consult your system documentation) and append the following lines at the end:
LoadModule python_module modules/mod_python.so AddHandler mod_python .psp .psp_ PythonHandler mod_python.psp PythonDebug On
The first line loads mod_python into Apache. The actual path of mod_python.so may vary but the installer should give you the proper path upon finishing. (On Linux most likely it would be libexec/mod_python.so.) The second line informs Apache which files should be handled by PythonHandler, specified on the third line (more about .psp_ usage in the section below). The last directive switches mod_python into debugging mode; when PythonDebug directive is set to On, it will dump traces for the first unhandled exception in the running application. Setting this flag is highly recommended for development purposes, but make sure you turn it off on production environments so as to not expose certain system internals to visitors.If you would like mod_python pages to be used as default index pages, locate in httpd.conf the following line and change it from
DirectoryIndex index.html index.html.varto
DirectoryIndex index.html index.psp index.html.var
Now restart Apache. On Windows you usually do that with the Apache Monitor in the system tray or by running net stop apache2 and then net start apache2; on Linux it's as simple as apachectl restart.
PSP are plain text files that include Python code surrounded with <% and %> tags. Python expressions are enclosed within <%= and %> tags. Directives enable inclusion of other PSP pages; they are wrapped by <%@ and %> tags. The least frequently used tags are <%-- and --%> which, as you might guess, are simply comments that are never rendered to the resulting code.
Let's start with the simple Hello Python example. Under APACHE_HOME/htdocs create a file hello.psp with the following content:
<html> <% import sys %> Hello! You have <%=len(sys.modules)%> Python modules at your command. </html>
Now go to http://127.0.0.1/hello.psp with your web browser. You will see how many Python modules are installed on your system. Of course, this information is trivial to us. Mod_python doesn't offer a function equivalent to PHP's phpinfo(), which gives detailed information about the interpreter. In the next step, we'll write one for PSP ourselves.
Under APACHE_HOME/htdocs, create a file pspinfo.psp with the following content:
<%% req.content_type = 'text/plain' import mod_python import pprint import sys %> PYTHON <%%=sys.version %> MOD_PYTHON <%%=mod_python.version %> PATH = <%%=pprint.pformat(sys.path)%> AVAILABLE MODULES <%%=pprint.pformat(sys.modules)%>
Now open http://127.0.0.1/pspinfo.psp and you should see results similar to those shown below.
PSP uses Python code to output parts of the page using blocks which are distinguished by indentation (like Python itself). The last indentation will persists until either the end of the document or until another Python block. Take a look at the following example (blocks.psp).
<% for i in range(5): j = 2**i # Loop block begins %> <%="%d<sup>%d</sup>=%d"%(2, i, j)%> <% # This will close the loop block %> Outside the loop block
In above example, I've used code blocks ( <% %>) and expressions ( <%= %>) together. When writing own scripts, please mind the difference between them: expression can contain only a single Python statement. If you find this notation hard to follow, let's revisit the Apache configuration from the previous step. Remember the AddHandler mod_python .psp .psp_ directive? Now we will make use of the debugging .psp_ address to see what's happening behind the scenes. When you go to http://127.0.0.1/blocks.psp you'll see PSP-produced Python Code and the source code, side by side.
This give an excellent in-depth look into the rendering engine. It also explains the logic behind mod_python engine: before execution, PSP pages get rendered into pure Python code.
The last information you need to begin developing basic PSP applications are sessions and form handling. Consider the following example of a basic login scenario (basic_login.psp). The password provided on the page should be a reversed UID:
<% if 'uid' in form and 'passwd' in form and form['passwd']==''.join(reversed(form['uid'])): session['uid'] = form['uid'] %> user <%=session['uid']%> logged in <% else: %> <form action="basic_login.psp"> UID<br/><input type="text" name="uid"/><br/><br/> Password<br/><input type="password" name="passwd"/><br/><br/> <input type="submit" value="Login"/> </form> <% # %>
PSP features two essential global variables, form and session. These are standard Python dictionaries. They give you maximum flexibility but be careful when assigning variables as they are not protected against being overwritten. You set session variables simply by setting key values of session dictionary variable:
session['variable'] = value
Note that Python does not limit you to use strings or integers as dictionary keys—any hashable value will fit. You can, for example, store a file object in the session pool to refer to it at any time during the session. Mod_python treats GET and POST requests equally, storing them in the form dictionary, making it easy to check whether the value has been set by the user. Python dictionaries have some very useful built-in methods, the most usable at this point are:
cx_Oracle Python module allows easy access to Oracle Database. It has been developed by Anthony Tuininga (Computronix) in conformance to the DB API 2.0 specification, which means you use the same set of methods and properties you can use to connect to MySQL or PostgreSQL.
Cx_Oracle has all the methods and properties of DB API 2.0 specification ( PEP 249) except the nextset() cursor method and Binary() constructor. Note however that cx_Oracle introduces many own extensions to the standard API, which greatly enhances working with Oracle databases. Each such extension is clearly marked in cx_Oracle documentation but basically, if you have already used DB API 2.0 in the past, you should feel like home.
Installing cx_OracleOn Windows:
As I've mentioned earlier, cx_Oracle is based on DB API 2.0 specification, which makes it extremely easy to use. Consider the following example to familiarize with the basic steps for connecting to the database and issuing queries. Create a file ora.psp under APACHE_HOME/htdocs to see whether the cx_Oracle module is working properly. (Replace username and passwords with values applicable to your configuration.):
<% import cx_Oracle db = cx_Oracle.connect('username', 'password', '127.0.0.1/XE') c = db.cursor() c.execute('select * from dual') req.write(c.fetchall()) db.close() %>
When you open http://127.0.0.1/ora.psp you should see the X character in your browser as the only value in the system DUAL table.
You have just set up a complete working environment for PSP and Oracle Database 10g and also learned the basics of Python Web development. You can now follow this trail and begin writing more complex applications with PSP or switch to mod_python's Publisher Handler, which provides a better MVC (Model-View-Controller) strategy.
There are several application frameworks available for Python currently. They are not refined enough to be used in enterprise-grade environments, although I recommend you give them a try. Apache with mod_python itself is powerful enough to handle most of the development scenarios.
Przemyslaw Piotrowski is an information technology specialist working with emerging technologies and dynamic, agile development environments. Having a strong IT background that includes administration, development and design, he finds many paths of software interoperability.