1. CGI Programming in Python
This CGI Programming in Python tutorial deals with the ‘cgi’ module, the support module for CGI scripts in Python. We’ll discuss the functionalities offered. Let’s begin.
2. Introduction to Python CGI
CGI stands for Common Gateway Interface. An HTTP server invokes a CGI script so it can process user input that a user may submit through an HTML <FORM> or <ISINDEX> element.
Such a script usually lives in the server’s special cgi-bin directory. For a request, the server places information about it- the client’s hostname, the requested URL, the query string, and other information- in the script’s shell environment. It executes this script and sends the output back to the client.
The input for this script connects to the client, and server sometimes reads the form data this way. Other times, it passes form data through a query string, which is a part of the URL. A query string holds data that doesn’t conventionally fit a hierarchical path structure. For example:
The module cgi handles situations and helps debug scripts. With the latest addition, it also lends us support for uploading files from a form.
So, what does a CGI script output? It gives out two sections separated by a blank line. Of these, the first section holds headers that instruct the client that a certain kind of data follows. Let’s try generating a minimal header section in this Python CGI Programming Example.
print("Content-Type: text/html") print()
The first statement tells the server that html code follows; the second(a blank line) indicates the end of the header. And then, the second section is the HTML. This lets the client software display formatted text:
print("<TITLE>CGI Script Output</TITLE>") print("<H1>This is our first CGI script</H1>") print("Hello, world!")
Let’s take a look at the architecture.
Next in the CGI programming in Python tutorial is CGI Module.
3. The cgi Module
Let’s begin with the cgi module. First, let’s import it.
>>> import cgi >>>
Now, we type this to write a new scipt:
>>> import cgitb >>> cgitb.enable() >>>
What this does is that it activates an exception handler to display detailed reports in the web browser in event of an error. If however, you want to save the reports to a file, you can:
>>> import cgitb >>> cgitb.enable(display=0, logdir="/path/to/logdir")
We can do this while developing a script. These reports help us track down bugs faster. Once we’re confident that our script works correctly, we can remove this.
Now, we use the class FieldStorage to work with the submitted form data. We can set the encoding keyword parameter to the encoding defined for the document if the form holds non-ASCII characters. You’ll find this is the <META> tag in the <HEAD> section of your HTML document. Alternatively, you may find it in the Content-type header. FieldStorage reads form contents from the standard input or from the environment. Instantiate it only once because it may consume standard input.
We can index a FieldStorage instance like a Python dictionary. This lets us test membership with the ‘in’ operator. We can then also call method keys() and function len(). Note that it ignores fields with empty string values. If we want to keep them, we can provide a True value for the optional keyword parameter keep_blank_values at the time of creating a FieldStorage instance.
Take a look at this code that ensures that fields ‘name’ and ‘addr’ are set to a non-empty string:
form = cgi.FieldStorage() if "name" not in form or "addr" not in form: print("<H1>Error</H1>") print("Please fill in the name and addr fields.") return print("<p>name:", form["name"].value) print("<p>addr:", form["addr"].value)
…further form processing here…
The fields that we access through form[key] are instances of FieldStorage. If there’s more than one field with the same name, this retrieves a list of instances of FieldStorage or MiniField Storage. The getlist() method returns a list of values:
value = form.getlist("username") usernames = ",".join(value)
Consider the situation when a field denotes an uploaded file. When we access the value using the attribute ‘value’, or using the method getvalue(), it reads the entire file in memory as bytes. To test for an uploaded file, we can test either the ‘filename’ attribute or the ‘file’ attribute. Then, we can read the data from the ‘file’ attribute before it automatically closes as a part of the garbage collection of the FieldStorage instance:
fileitem = form["userfile"] if fileitem.file: #It's an uploaded file; count lines linecount = 0 while True: line = fileitem.file.readline() if not line: break linecount = linecount + 1
We can also use a FieldStorage object in a with-statement. It automatically closes it when done.
If an error occurs obtaining an uploaded file’s contents, like if a user interrupts form submission pressing Back or Cancel, it sets the ‘done’ attribute for the object for the field to -1.
It is possible that the user uploads multiple files from one field. Then, the item is a dictionary-like FieldStorage item. We can test its ‘type’ attribute to determine this. This should be multipart/form-data. We can recursively iterate over it like the top-level form object.
When a user submits a form in the old format- as a query string, this makes the items instances of MiniFieldStorage. This makes the attributes ‘list’, ‘file’, and ‘filename’ attributes equal to None. Forms submitted through POST also have a query string holding both FieldStorage and MiniFieldStorage items.
Any doubt yet in CGI programming in Python? Please Comment.
For more control over your CGI programming in Python, you can use the following functions:
a. cgi.parse(fp=None, environ=os.environ, keep_blank_values=False, strict_parsing=False)
This will parse a query in the environment. We can also make it do so from a file, the default for which is sys.stdin.
b. cgi.parse_qs(qs, keep_blank_values=False, strict_parsing=False)
While this is deprecated, Python maintains it for backward-compatibility. But we can use urllib.parse.parse_qs() instead.
c. cgi.parse_qsl(qs, keep_blank_values=False, strict_parsing=False)
This is deprecated too, and is maintained for backward-compatibility. You may use urllib.parse.parse_qsl() instead.
d. cgi.parse_multipart(fp, pdict)
This function will parse input of type multipart/form-data for file uploads. The first argument takes the input file, and the second takes a dictionary holding other parameters in the Content-Type header.
parse_header() passes a MIME header into a main value and into a dictionary of parameters.
This function is a test CGI script, and we can use it as the main program. It will write minimal HTTP headers and formats.
This formats the shell environment in HTML.
This function formats a form in HTML.
This will format the current directory in HTML.
This prints a list of all useful environment variables in HTML.
k. cgi.escape(s, quote=False)
escape() will convert characters ‘<’, ‘>’, and ‘&’ in the string ‘s’ to HTML-safe sequences. If you must display text holding such characters, you may use this in HTML.
This was all on CGI Programming in Python.
Isn’t this interesting? Tell us what you think about this CGI programming in Python tutorial in the comment box.