Python action page

In contrast to PHP, which copies html directly to output, python scripts are true programs, which must print all the output. In addition, Apache doesn't "know" this, so by default would just send out the python code, not what you want.

Program starts like this:
#!/usr/bin/python
# -*- coding: utf-8 -*-
print "Content-Type: text/html; charset=UTF-8" # ALWAYS this header (HTML is following)
#--that takes care of charset!
# more headers, such as Set-Cookie:
print # blank line, end of headers

print """<!DOCTYPE HTML>
<html lang="en">
<head>
<title>Python demonstration</title>
<!-- all the head information you want here -->
</head>
<body>"""

Useful modules

cgi  - get query string

This module is imported, and provides storage for the form data, which is an object with "methods" from which one may get the data coming from a form

import cgi
form=cgi.FieldStorage()
who = form.getvalue('who') # we expect certain fields to be there, value may be None if field is left blank
names = form.keys() # all the input names for which values exist
sports = form.getlist('sports') # which might be a <select multiple name="sports">
"sports" may appearseveral times in the query string, in which case form.getvalue('sports') will return a list. But if only one sport is selected, it would return a simple value instead. getlist returns a list of one element in this case. Note that awkward names like "sports[]" are not needed.

psycopg2  - module for PostgreSQL

Here you open a connection, create a cursor (or more), with which to execute SQL commands and fetch the results. fetchone() gets one row (as a "tuple"), fetchall() gets a list of tuples.
import psycopg2
try:
con=psycopg2.connect('dbname=fruitstand host=localhost user=mickey password=MoUsE')
except:
print "Database connect trouble"
import sys
sys.exit()
curs=con.cursor() # extra object that manages query execution
# get a dictionary of prices
curs.execute("select trim(name), price from fruit where stock>0")
prices={}
for f,p in curs.fetchall(): # loop through all the rows
prices[f]=float(p)
Values go in and out of the database as strings, here we needed to convert price to a float, since it is going to be used numerically. See the python tutorial at www.python.org for the distinction between tuple, list, and dictionary, represented with (), [], and {} respectively.

Transactions: What if SQL statements fail?

A transaction in SQL is considered an atomic operaction, it either completes without error, or is "rolled back" leaving the database unchanged. In psql, each statement (and anything invoked by its rules) is considered an atomic transaction. We have seen one fail: Ordering a large number of bananas causes the inventory to be updated, and that fails if the result would be negative, causing the ordre to fail. What should happen with the res of the order. PHP would go ahead, after perhaps printing an error message, this is referred to as "autocommit."

Python takes the opposite view, regarding the whole program as a single all-or-nothing transaction. this can be altered in two ways. We can set autocommit on the connection, or issue explicit commit or rollback instructions to the connection (after the cursor has processed a statement that might fail. Responsibilities are divided here between the two objects.) Here is an example from fruitorder.py:

try:			# insert might fail if not enough stock
 curs.execute("insert into sold values (%s,%s)", (fruit,qty)) # like pg_query_params
price=prices[fruit] # look up in a dict!
print "<tr><td>%s</td><td>%d</td><td>%.2f</td><td>%.2f</td> </tr>" %\ #continuation line
(fruit, qty, price, qty*price) #insert values at the %'s
sum += qty*price
con.commit() # make this permanent
except:
con.rollback() #acknowledge failure, reset connection to allow further queries
print "<tr><td>%s</td><td colspan=3>Sorry, we don't have %d</td></tr>" %\
 (fruit, qty)

Learning Python

The best way to learn Python is to follow the tutorial, and test it out. You can run Python interactively in a terminal, and try out statements you want to use. here is an example showing the diference between a tuple (immutable) and a list:
[jensen@lindgren ~]$ python
>>> t=(2,4,8) # I type
>>> t[1]
4 # system response
>>> t[1]=44
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'tuple' object does not support item assignment
>>> l=[2,4,8]
>>> l[1]=44
>>> l
[2, 44, 8]
>>> l=l+[7,77,'hello']
>>> l
[2, 44, 8, 7, 77, 'hello']
>>> l.pop(2)
8
>>> l
[2, 44, 7, 77, 'hello']
>>> quit
Use quit() or Ctrl-D (i.e. EOF) to exit
>>> quit()
[jensen@lindgren ~]$

To get help on any "object" type help(l) for example, to find out what you can do with the list l