Recipe 14.1. Testing Whether CGI Is Working
Credit: Jeff Bauer, Carey Evans
Problem
You
want a simple CGI (Common Gateway Interface) program to use as a
starting point for your own CGI programming or to determine whether
your setup is functioning properly.
Solution
The cgi module is normally used in Python CGI
programming, but here we use only its escape
function to ensure that the value of an environment variable
doesn't accidentally look to the browser as HTML
markup. We do all of the real work ourselves in the following script:
#!/usr/local/bin/python
print "Content-type: text/html"
print "<html><head><title>Situation snapshot</title></head><body><pre>"
import sys
sys.stderr = sys.stdout
import os
from cgi import escape
print "<strong>Python %s</strong>" % sys.version
keys = os.environ.keys( )
keys.sort( )
for k in keys:
print "%s\t%s" % (escape(k), escape(os.environ[k]))
print "</pre></body></html>"
Discussion
CGI is a standard that specifies how a web server runs a separate
program (often known as a CGI script) that generates a web page
dynamically. The protocol specifies how the server provides input and
environment data to the script and how the script generates output in
return. You can use any language to write your CGI scripts, and
Python is well suited for the task.This recipe is a simple CGI program that takes no input and just
displays the current version of Python and the environment values.
CGI programmers should always have some simple code handy to drop
into their cgi-bin directories. You should run
this script before wasting time slogging through your Apache
configuration files (or whatever other web server you want to use for
CGI work). Of course, cgi.test does all this and
more, but it may, in fact, do too much. It does so much, and so much
is hidden inside cgi's innards,
that it's hard to tweak it to reproduce any specific
problems you may be encountering in true scripts. Tweaking the
program in this recipe, on the other hand, is very easy, since
it's such a simple program, and all the parts are
exposed.Besides, this little script is already quite instructive in its own
way. The starting line, #!/usr/local/bin/python,
must give the absolute path to the Python interpreter with which you
want to run your CGI scripts, so you may need to edit it accordingly.
A popular solution for non-CGI scripts is to have a first line (the
so-called shebang line) that looks something
like this:
#!/usr/bin/env pythonHowever, this approach puts you at the mercy of the
PATH environment setting, since it runs the first
program named python that it finds on the
PATH, and that may well not be what you want under
CGI, where you don't fully control the environment.
Incidentally, many web servers implement the shebang line even when
running under non-Unix systems, so that, for CGI use specifically,
it's not unusual to see Python scripts on Windows
start with a first line such as:
#!c:/python23/python.exeAnother issue you may be contemplating is why the
import statements are not right at the start of
the script, as is the usual Python style, but are preceded by a few
print statements. The reason is that
import could fail if the Python installation is
terribly misconfigured. In case of failure, Python emits diagnostics
to standard error (which is typically directed to your web server
logs, depending on how you set up and configured your web server),
and nothing will go to standard output. The CGI standard demands that
all output be on standard output, so we first ensure that a minimal
quantity of output will display a result to a visiting browser. Then,
assuming that import sys succeeds (if it fails,
the whole Python installation is so badly broken that you can do very
little about it!), we immediately perform the following assignment:
sys.stderr = sys.stdoutThis assignment statement ensures that error output will go to
standard output, so that you'll have a chance to see
it in the visiting browser. You can perform other
import operations or do further work in the script
only when this is done. Another option makes getting tracebacks for
errors in CGI scripts much simpler. Simply add the following at the
start of your script:
import cgitb; cgitb.enable( )and the standard Python library module cgitb takes
care of whatever else is needed to get error tracebacks on the
browser. However, as already stated, the point of this recipe is to
show how everything is done, rather than just reusing prepackaged
funcitonality.One last reflection is that, in Python 2.4, instead of the three
lines:
keys = os.environ.keys( )used in the recipe, you could use the single line:
keys.sort( )
for k in keys:
for k in sorted(os.environ):Unfortunately, since CGI scripts must often run in environments you
do not control, I cannot suggest you code to a specific, recent
version of Python in this particular caseparticularly not a
script such as this one, which is meant to let you examine and check
out the exact circumstances under which your CGI runs.Yet another consideration, not strictly related to Python, is that
this script is coded to emit correct HTML. Just about all known
browsers let you get away with skipping most of the HTML tags that
this script outputs, but why skimp on correctness, relying on the
browser to patch your holes? It costs little to emit correct HMTL, so
you should get into the habit of doing things right, when the cost is
so modest. (I wish more authors of web pages, and of programs
producing web pages, shared this sentiment. If they did, there would
be a lot less broken HTML out on the Web!)
See Also
Documentation on the cgi and
cgitb standard library modules in the
Library Reference and Python in a
Nutshell; a basic introduction to the CGI protocol is
available at http://hoohoo.ncsa.uiuc.edu/cgi/overviewl.