Mention Common Gateway Interface scripting to a Web developer, and their first response is likely to be "I use Perl." While Perl has long dominated the CGI scripting world, there are other, and perhaps better, tools available. In this tutorial we'll take a look at CGI scripting with Python, a fast, versatile, multi-platform language.
Python is an interpreted, object-oriented language named after the BBC television show "Monty Python's Flying Circus." No johnny-come-lately, Python's first release was in 1991. Developed by Guido van Rossum, Python is the scripting language of choice for many enterprises, including Google, NASA, and ForecastWatch.com.
For the purpose of this tutorial, we'll assume that you have minimal experience with Python. Beginners are advised to browse one of the many excellent Python references available online, such as the Python tutorial or the Python reference manual.
Make certain that Python is installed on your development system. From a shell prompt, type
python -V. If Python is installed and in your path it should print the version number (we're using 2.5.1) and exit. If you don't have Python installed, use a package management tool such as yum or apt-get to download and install Python from a repository.
Once you've confirmed that Python is installed on your system, the next step is to verify that you have configured your Web server to allow CGI scripting. We'll be using the Apache Web server for our tutorial. If you don't have root access or sudo privileges, you'll need to ask your systems administrator for assistance with the following instructions.
Edit /etc/httpd/conf/httpd.conf. Search for a block of text beginning with
#ScriptAlias: This controls which directories contain server scripts. and make certain that your configuration file looks like this:
# "/var/www/cgi-bin" should be changed to whatever your ScriptAliased
# CGI directory exists, if you have that configured.
Allow from all
If your httpd.conf file doesn't exactly match the above text, don't worry. While most installations are configured to allow CGI scripting, your configuration file may have CGI capacity commented out. Check for a '#' character preceding the ScriptAlias directive. If you find one, remove it, save the httpd.conf file, and restart Apache using
Your first script
Using a text editor, create a file called example1.py and enter the following lines:
print "Content-type: text/html"
print "<center>Hello, Linux.com!</center>"
Save the file in /var/www/cgi-bin (you'll need to be root or have sudo access) and make sure that the file is executable by setting permissions with
chmod 755 example1.py.
Using a Web browser, open the file by entering the file's URL: http://yourtesthost.com/var/www/cgi-bin/example1.py. Make sure that you don't try to open the file directly using the File -> Open menu selection; you need to retrieve the file via a Web server for this to work. You should see "Hello, Linux.com!" centered in your browser window if all went well. If not, double-check first.py and make sure your code matches our example. It's important that you don't leave out the empty
"Content-type: text/html" entry. The lack of a blank line will result in an internal server error.
An easy way to verify your syntax is to execute the file directly by entering
./example1.py. If your code is correct, Python should execute the file and print the HTML code as plain text. While useful for checking syntax, this technique won't help you debug more advanced CGI scripts. A CGI script won't always perform perfectly from the command line, and a script that executes properly from the command line may crash and burn when invoked by the Web server.
More sophisticated scripts require some additions to your coding toolkit. It's time to take a look at the cgi and cgitb modules.
Included with the standard Python distribution, the cgi and cgitb modules provide enhanced functionality for writing and debugging CGI applications. The cgi module defines several classes, including the FieldStorage class, which we'll use to build our second example: a forms-based script. The cgitb module is a debugger and will prove useful when we start writing scripts longer than a few lines. We'll use cgitb to help us debug our third script.
Our sample script is a short questionnaire that asks two questions and tabulates the results. Follow the same procedure we used in our first example and create a file called example2.py. Copy and paste the following code into example2.py and save the file in /var/www/cgi-bin. Don't forget to make the file executable using
chmod 755 second.py.
print "Content-type: text/html"
form = cgi.FieldStorage()
laptops = form.getvalue('laptops','0')
desktops = form.getvalue('desktops','0')
How many laptops do you own?
<input type='radio' checked name='laptops' value='0' />0
<input type='radio' name='laptops' value='1' />1
<input type='radio' name='laptops' value='2' />2
How many desktops do you own?
<input type='radio' checked name='desktops' value='0' />0
<input type='radio' name='desktops' value='1' />1
<input type='radio' name='desktops' value='2' />2
<input type='submit' />
You own %d computers.
</html>""" % (int(laptops)+int(desktops))
Example2.py differs from our first example in several ways. Note the inclusion of the cgi module on line two and the form creation statement on line five. We'll be using the FieldStorage class to retrieve data from our form as shown in lines six and seven. The rest of example2.py is standard HTML. Make sure example2.py is in your cgi-bin directory and load the URL of example2.py using your Web browser. The file should load and display a two-line questionnaire asking you to list the number of laptop and desktop computers you own. Your answers will be totaled and displayed at the bottom of the form. Try changing your answers and submitting the form to verify proper operation.
Debugging with cgitb
Code that works the first time you test it is always a pleasant surprise, but we're not always that lucky. The standard error messages provided by httpd can be less than helpful when you're trying to track down a problem. Using a debugger like cgitb can mean the difference between puzzling through perplexing error messages and quickly identifying the source of the problem. To demonstrate how helpful cgitb can be, we're going to introduce an error into our second script and use cgitb to sniff out the bad code.
Edit example2.py and scroll to the last line of the file. You'll see a line containing the statement
(int(laptops) + int(desktops)). Change the plus sign to a division sign --
(int(laptops) / int(desktops)) -- and save the file. Reload the URL of example2.py with your Web browser. You should see a big difference from the first time we ran this script: you're presented with a blank page. Our introduced error has turned a working script into one that won't execute and that provides no useful debugging output.
Open example2.py and add the following two lines to the top of the file, directly under the
import cgi statment:
Save the file in /var/www/cgi-bin and reload the URL. Notice the difference? Instead of a blank Web page we now have a detailed report on exactly what is wrong with our sample script. Cgitb tells us that we have a ZeroDivisionError: integer division or modulo by zero. Change the division symbol back to a plus sign, save example2.py, and reload. Example2.py should now function properly.
Admittedly, finding a single incorrect arithmetic operator doesn't take sophisticated debugging skills, and we would have noticed our mistake quickly. Most scripts, however, aren't as short as our example. An incorrect entry in a large and complex script can mean spending hours of debugging time. Cgitb can help you minimize the time spent tracking down typos.
We didn't have the space to demonstrate more than a small sample of what Python is capable of when used for CGI scripting, but we hope that we've aroused your interest in learning more. Some good choices for further reading are Magnus Lie Hetland's Beginning Python: From Novice to Professional and O'Reilly's Programming Python, Third Edition by Mark Lutz.