How to create and use Python CGI scripts

Have you ever wanted to create a webpage or process user input from a web-based form using Python? These tasks can be accomplished through the use of Python CGI (Common Gateway Interface) scripts with an Apache web server. CGI scripts are called by a web server when a user requests a particular URL or interacts with the webpage (such as clicking a "Submit" button). After the CGI script is called and finishes executing, the output is used by the web server to create a webpage displayed to the user.

Configuring the Apache web server to run CGI scripts

In this tutorial we assume that an Apache web server is already set up and running. This tutorial uses an Apache web server (version 2.2.15 on CentOS release 6.5) that is hosted at the localhost (127.0.0.1) and is listening on port 80, as specified by the following Apache directives:

ServerName 127.0.0.1:80
Listen 80

HTML files used in the upcoming examples are located in /var/www/html on the web server. This is specified via the DocumentRoot directive (specifies the directory that webpages are located in):

DocumentRoot "/var/www/html"

Consider a request for the URL: http://localhost/page1.html

This will return the contents of the following file on the web server:

/var/www/html/page1.html

To enable use of CGI scripts, we must specify where CGI scripts are located on the web server. To do this, we use the ScriptAlias directive:

ScriptAlias /cgi-bin/ "/var/www/cgi-bin/"

The above directive indicates that CGI scripts are contained in the /var/www/cgi-bin directory on the web server and that inclusion of /cgi-bin/ in the requested URL will search this directory for the CGI script of interest.

We must also explicitly permit the execution of CGI scripts in the /var/www/cgi-bin directory and specify the file extensions of CGI scripts. To do this, we use the following directives:

<Directory "/var/www/cgi-bin">
    Options +ExecCGI
    AddHandler cgi-script .py
</Directory>

Consider a request for the URL: http://localhost/cgi-bin/myscript-1.py

This will call the following script on the web server:

/var/www/cgi-bin/myscript-1.py

Creating a CGI script

Before creating a Python CGI script, you will need to confirm that you have Python installed (this is generally installed by default, however the installed version may vary). Scripts in this tutorial are created using Python version 2.6.6. You can check your version of Python from the command line by entering either of the following commands (the -V and --version options display the version of Python that is installed):

$ python -V
$ python --version

If your Python CGI script will be used to process user-entered data (from a web-based input form), then you will need to import the Python cgi module. This module provides functionality for accessing data that users have entered into web-based input forms. You can import this module via the following statement in your script:

import cgi

You must also change the execute permissions for the Python CGI script so that it can be called by the web server. Add execute permissions for others via the following command:

# chmod o+x myscript-1.py

Python CGI Examples

Two scenarios involving Python CGI scripts will be considered in this tutorial:

  1. Create a webpage using a Python script
  2. Read and display user-entered data and display results in a webpage

Note that the Python cgi module is required for Scenario 2 because this involves accessing user-entered data from web-based input forms.

Example 1: Create a webpage using a Python script

For this scenario, we will start by creating a webpage /var/www/html/page1.html with a single submit button:

<html>
<h1>Test Page 1</h1>
<form name="input" action="/cgi-bin/myscript-1.py" method="get">
<input type="submit" value="Submit">
</form>
</html>

When the "Submit" button is clicked, the /var/www/cgi-bin/myscript-1.py script is called (specified by the action parameter). A "GET" request is specified by setting the method parameter equal to "get". This requests that the web server return the specified webpage. An image of /var/www/html/page1.html as viewed from within a web browser is shown below:

The contents of /var/www/cgi-bin/myscript-1.py are:

#!/usr/bin/python
print "Content-Type: text/html"
print ""
print "<html>"
print "<h2>CGI Script Output</h2>"
print "<p>This page was generated by a Python CGI script.</p>"
print "</html>"

The first statement indicates that this is a Python script to be run with the /usr/bin/python command. The print "Content-Type: text/html" statement is required so that the web server knows what type of output it is receiving from the CGI script. The remaining statements are used to print the text of the webpage in HTML format.

When the "Submit" button is clicked in the above webpage, the following webpage is returned:

The take-home point with this example is that you have the freedom to decide what information is returned by the CGI script. This could include the contents of log files, a list of users currently logged on, or today's date. The possibilities are endless given that you have the entire Python library at your disposal.

Example 2: Read and display user-entered data and display results in a webpage

For this scenario, we will start by creating a webpage /var/www/html/page2.html with three input fields and a submit button:

<html>
<h1>Test Page 2</h1>
<form name="input" action="/cgi-bin/myscript-2.py" method="get">
First Name: <input type="text" name="firstName"><br>
Last Name: <input type="text" name="lastName"><br>
Position: <input type="text" name="position"><br>
<input type="submit" value="Submit">
</form>
</html>

When the "Submit" button is clicked, the /var/www/cgi-bin/myscript-2.py script is called (specified by the action parameter). An image of /var/www/html/page2.html as viewed from within a web browser is shown below (note that the three input fields have already been filled in):

The contents of /var/www/cgi-bin/myscript-2.py are:

#!/usr/bin/python
import cgi
form = cgi.FieldStorage()
print "Content-Type: text/html"
print ""
print "<html>"
print "<h2>CGI Script Output</h2>"
print "<p>"
print "The user entered data are:<br>"
print "<b>First Name:</b> " + form["firstName"].value + "<br>"
print "<b>Last Name:</b> " + form["lastName"].value + "<br>"
print "<b>Position:</b> " + form["position"].value + "<br>"
print "</p>"
print "</html>"

As mentioned previously, the import cgi statement is needed to enable functionality for accessing user-entered data from web-based input forms. The web-based input form is encapsulated in the form object, which is a cgi.FieldStorage object. Once again, the "Content-Type: text/html" line is required so that the web server knows what type of output it is receiving from the CGI script. The data entered by the user are accessed in the statements that contain form["firstName"].value, form["lastName"].value, and form["position"].value. The names in the square brackets correspond to the values of the name parameters defined in the text input fields in /var/www/html/page2.html.

When the "Submit" button is clicked in the above webpage, the following webpage is returned:

The take-home point with this example is that you can easily read and display user-entered data from web-based input forms. In addition to processing data as strings, you can also use Python to convert user-entered data to numbers that can be used in numerical calculations.

Summary

This tutorial demonstrates how Python CGI scripts are useful for creating webpages and for processing user-entered data from web-based input forms. More information about Apache CGI scripts can be found here and more information about the Python cgi module can be found here.


Subscribe to Xmodulo

Do you want to receive Linux FAQs, detailed tutorials and tips published at Xmodulo? Enter your email address below, and we will deliver our Linux posts straight to your email box, for free. Delivery powered by Google Feedburner.


Support Xmodulo

Did you find this tutorial helpful? Then please be generous and support Xmodulo!

The following two tabs change content below.
Joshua Reed is a graduate student and IT programming intern. He loves solving challenging problems by combining the realms of Linux, physics, programming, and software. In his free time he enjoys playing guitar and listening to rock, chillstep, and trance music.

5 thoughts on “How to create and use Python CGI scripts

  1. A very useful overview. At the moment I'm trying to get my head around something similar in Tcl/Tk and your primer helps a lot.

  2. Good basic tutorial.

    Two comments.

    You need a title tag in all html pages. That is actually the only tag in a html document that is needed. All other are optional.

    There are a real semantic and conceptual difference between post and get in http.
    Get just get information, never change any data in the server. Never store any data in a database for the user. So it doesn't matter if you reload the page as you will get the da able result.
    Post always store/change data in the server, like store/change data in a database. So a reload could/will change the server and could give different result.

    The difference is shown when you push the back button. A get is allowed as it will get the same result no matter how many times you reload the page. Post on the other hand makes the web browser to ask if you really want to reload this page. As it will/could change the state of the Web server.

  3. Hi Joshua Sir,
    I configured everything as you said, but still it's not working. The HTML page is loading, but it isn't invoking the CGI SCRIPT. As soon, as I click on SUBMIT, it says FILE NOT FOUND. I checked the error.log and THERE IS NOTHING LOGGED in the error file . What could be the problem ?
    I didn't touch the apache.conf though
    Here are the contents of my /etc/apache2/sites-available/000-default.conf

    ServerAdmin webmaster@localhost
    DocumentRoot /var/www/

    Options FollowSymLinks
    AllowOverride None

    Options Indexes FollowSymLinks MultiViews
    AllowOverride None
    Order allow,deny
    allow from all

    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined

    AddHandler mod_python .py
    PythonHandler hello
    PythonDebug On

    Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch

    AddHandler cgi-script .cgi .pl .rb .py .pyc

    Order allow,deny

    Allow from all

    ScriptAlias /cgi-bin/ /var/www/cgi-bin/

    AllowOverride None
    Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
    Order allow,deny
    Allow from all
    AddHandler cgi-script .py
    AddHandler default-handler .html .htm

Leave a comment

Your email address will not be published. Required fields are marked *