Sei sulla pagina 1di 19

Lesson 1: The Basics

Please, read the FAQ before starting. This tutorial assumes that you (or your system administrators) have installed a Web server and the Python interpreter correctly. For more information on these topics, check your Web server documentation and the Python Language Website. Once you have the server and interpreter up and running, the following simple CGI program serves as a good test. o o o o o Copy the program text from the gray box below and save it in ASCII text format as "example_1.1.cgi". Place the file in your CGI directory ( /cgi-bin/ on most Unix machines). For Unix/Linux users, be sure to change the permissions to make the script executable (chmod +x example_1.1.cgi). Open your Web browser, and type the URL path to the file (i.e., http://your_url_here/cgibin/example_1.1.cgi) To generate output to compare your results against, click the button below.

Code Example 1.1:


#!/usr/bin/python # Required header that tells the browser how to render the text. print "Content-Type: text/plain\n\n" # Print a simple message to the display window. print "Hello, World!\n" So, what do the parts of this file mean? Let's look at the code line by line. Technically, the first line is a comment, as are all lines that begin with a ' # ' in Python. This comment is special because it tells the Unix/Linux systems where to locate the Python interpreter, which in turn runs the rest of the code file. Unix/Linux users should verify that this is the correct path to their interpreter. On other platforms, the operating system locates the interpreter by different methods, and the Python interpreter ignores the first line [1, 2: 14]. The second line of text is another comment ignored by the interpreter - this time intended for the human reader. It explains the purpose of the following print statement. The third line prints a text message to standard output. This message, "Content-Type: text/plain\n\n", tells the Web browser what type of information follows. It is specific just to CGI programming. Note that there are two new-line escape characters, "\n\n". This "\n" character works like pressing the "Enter" key on a keyboard. Since most browsers expect a blank line after the content type, the double "\n" works like pressing the "Enter" key twice to create a blank line before the next print statement [1]. The fourth line, another comment to the reader, explains that the next line of code will print to the window. The final line prints the text message "Hello, World!\n" to standard output. This time the browser knows how to display the text and prints it to the window area [1]. To Lesson 2 ...

Lesson 2: Variables in Python


Now that we have seen how a simple CGI program works, let's inspect how variables work in Python. All assignments have the syntax identifier = value. Identifier names can be begin with either an underscore or letter followed by any combination of letters, numbers, and underscores.

In addition, names are case sensitive (i.e., name is different from Name). Variables have dynamic type in Python, so there is no need to specify types in declarations [4]. Table 2.1 shows the variable types of Python with examples of each.

Table 2.1: Built-in Object Types [2: 28]


Type Numbers Strings Lists Dictionaries Tuples Files Example 12345, 1.5, 2e+10, 2e-10, 2+4j "Python", "CGI" ['this', ['is', 1], 'example'] {'Python':'good', 'CGI':'useful'} (1, 'two', 3, 'IV') input_file = open('data.txt','r').read()

The code examples below demonstrate various assignment methods and results.

Code Example 2.1:


#!/usr/bin/python # Print the required header that tells the browser how to render the text. print "Content-Type: text/plain\n\n" # Initialize a few variables. first = 5 middle = 7.5 last = 10 # Print the values. print "first:", first print "middle:", middle print "last:", last Multiple assignments can be done at once. Python handles a = b = c assignments in a right associative manner. In addition, Python performs a swap operation on the assignment: identifier_1, identifier_2 = identifier_2, identifier_1

Code Example 2.2:


#!/usr/bin/python # Print the required header that tells the browser how to render the text. print "Content-Type: text/plain\n\n"

# Initialize a few variables. first, middle, last = 5, 7.5, 10 # Print the values.

print "first:", first print "middle:", middle print "last:", last, "\n" # Swap the values. first, last = last, first # Print the values. print "first:", first print "last:", last, "\n" # Right associative assignment. first = last = middle # Print the values. print "first:", first print "middle:", middle print "last:", last

Python contains various operators for number, string, and list operand types. Table 2.2 shows the most common.

Table 2.2: Python Operators [2: 30]


Operator or and not ==, !=, <, <=, >, >=, <> in, not in +, *, / % a[i], a[i:n], a.b Description Logical OR Logical AND Logical NOT Comparison Sequence Membership Addition/String Concatenation, Subraction Multiplication/String Repetition, Division Modulus Indexing, Slicing, Qualification

Code Example 2.3 demonstrates the functionality of a few of the operators above. Pay close attention to the dynamic typing as a result of integer and decimal value calculations. Note that specifying a negative index works like counting back from the end of the string.

Code Example 2.3:


#!/usr/bin/python # Print the required header that tells the browser how to render the text. print "Content-Type: text/plain\n\n" # Integer division resulting in a truncated value. a = 5/2 # Print the value. print "5/2 =", a # Decimal division.

a = 5/2.0 # Print the value. print "5/2.0 =", a, "\n" # String addition and multiplication. python_words = "python is" + 3*" really" + " neat." # Print the string. print python_words, "\n" # Print parts of the string. print "The first character is:", python_words[0] print "The last character is:", python_words[-1] print "In the middle is: \n", python_words[1:-1] So far, we have covered numbers and strings fairly well. As we use more advanced features of the Python language, we will demonstrate the capabilities of lists, dictionaries, tuples, and files. To Lesson 3 ...

Lesson 3: Control Flow in Python


Control flow refers to altering the path taken through a program. Since Python executes a program line by line in sequential order, any statements that alter this path are known as controlflow statements. In Python, these statements are the if statement, while loop, and for loop [ 2:79].

if Statements The if statement has the syntax:


if condition: # Do something. elif another_condition: # Do something else. else: # Do something other than two options above.

The elif and else clauses are optional. The condition and another_condition tests can be a comparison statement (using logical or comparison operators) or a single variable. Since Python does not have a Boolean type, every type has Boolean properties. The values 0, "" (empty string), [ ] (empty list), { } (empty dictionary), and ( ) (empty tuple) equal a logical false. Every other value equals a logical true. Notice that Python does not use BEGIN/END or curly braces, { }, to denote compound or nested statments. This is indicated through indentation only [4]. Code Example 3.1 demonstrates the proper use of the if statement. Note the use of the logical and comparison operators from Lesson 2. Code Example 3.1:

#!/usr/bin/python # Print the required header that tells the browser how to render the text. print "Content-Type: text/plain\n\n" # Initialize a few variables. first_name = "Louis" last_name = "" # Empty String age = 21.5 # Test for name. if (first_name and last_name): print "Hello,", first_name, last_name print "It is good to see you, Mr.", last_name elif first_name: print "Hello,", first_name else: print "Who are you?" # Test for age. if (age >= 21): print "You can drink!" else: print "No drinks for you!"

while Loops The while loop has the syntax:


while condition: # Do something. else: # Do something else. The else clause is optional. In a while loop, the nested statement is repeated until the condition is false. The same properties for condition apply for while loops as they did for if statements. Code Example 3.2 shows a simple parse using a while loop and nested if statement.

Code Example 3.2:


#!/usr/bin/python # Print the required header that tells the browser how to render the text. print "Content-Type: text/plain\n\n" # Initialize a counting variable. counter = 1 # Print the even numbers from 1 to 10. while (counter <= 10): if ((counter%2) == 0): print counter counter = counter +1

print "Finished."

for Loops The for loop has the syntax:


for item in objects: # Do something. else: # Do something else. The else clause is optional. In a for loop, the nested statement is repeated until objects is exhausted. Each iteration the loop steps through the objects in a sequential order and item is assigned the value of an element of objects. If the loop is a counter from 0 to n, then the built-in function range(n + 1 ) can be called in place of objects. Code Example 3.3 shows simple counters using for loops and the range(n) function.

Code Example 3.3:


#!/usr/bin/python # Print the required header that tells the browser how to render the text. print "Content-Type: text/plain\n\n" # List of integers. numbers = [0, 1, 2] # Print iterations using numbers. for count in numbers: print "iteration", count # Print iterations using range(3). for count in range(3): print "iteration", count Now that we can control the data and flow of programs, we will look at breaking our programs into functions. We have already called a built-in function, range(n), and in the next section, we will look at creating our own. To Lesson 4 ...

Lesson 4: Python Functions


Functions provide the options of code reuse and decomposition of programs into managable parts [ 4, 2: 98]. In Python, function definitions have the syntax: def identifier (argument_1, argument_2, ..., argument_n): # Do something return value The def reserved word defines the function and the return reserved word sends a value back to the calling procedure. Functions are not required to have a return value. Therefore, the return is optional. List and dictionary arguments are passed by reference, meaning that any change to

their values remains after the function terminates. All other variable types are passed by value, and changes made to the variables are not carried beyond the local scope of the function. Function calls have the syntax: value = identifier(argument_1, argument_2, ..., argument_n) Typically, arguments are passed as positionals, and are matched left to right. They can be passed as keywords with the function arguments assigned to formal parameters in the function call. Additionly, arguments can be omitted if the function definition supplies default values. Code Example 4.1 demonstrates the typical variations of function calls.

Code Example 4.1:


#!/usr/bin/python # Print the required header that tells the browser how to render the text. print "Content-Type: text/plain\n\n" # Define a function with default argument 'age' = 21. def display_vars (first_name, last_name, age = 21): print (first_name, last_name, age) # Call the function with all positionals. display_vars("John", "Smith", 22) # Call the function with all keywords. display_vars(last_name = "Smith", first_name = "John", age = 22) # Call the function with incomplete args; default age used. display_vars("John", "Smith")

A Note on Variable Scope


Variables in Python can have one of three scopes: local, global, and built-in. Local variables are specific to their functions. Global variables are accessible anywhere in a program. Built-in variables are those defined in the Python language. An important aspect of scope in Python is that local names are detected statically. This means that a undefined local variable is not looked up in the calling procedure; it obtains its definition from the enclosing module [2: 117]. Code Example 4.2 demonstrates this feature.

Code Example 4.2:


#!/usr/bin/python # Print the required header that tells the browser how to render the text. print "Content-Type: text/plain\n\n" # Define a global variable gender = "female". gender = "female" # Define a function. def display_vars (first_name, last_name, age):

print (first_name, last_name, age, gender) # Define a function that calls 'display_vars' with intended local 'gender'. def go_display(): gender = "male" display_vars("John", "Smith", 22) # Call the function 'go_display'. go_display() Note that the Python interpreter did not look up the value of gender dynamically at runtime from the calling procedure. Instead, it found the value of gender by recursing the static chain of the compiled code, and therefore selected the logically incorrect value.

To Lesson 5 ...

Lesson 5: Python Modules


Now that we have learned how to manage data, control flow, and functions, we can look at more advanced high-level methods of constructing programs: modules. Modules are program files that clients can import into their own code for use. Whether it is a module designed by the creator of Python or one you create yourself, modules facilitate code reuse, namespace partitioning, and code sharing. In large-scale projects with many programmers, the ability to develop code in modules as blocks that can be share between one another is paramount [ 4, 2: 127]. Let's look at a simple module:

module_5.py:
# Module attribute that just prints. def simple_print(thing): print thing By saving the above file as module_5.py we have created our first module. In order to gain access to the code saved in module_5.py, we have to use the built-in function import at the top of our program. Once we import the module into our code, we must use the '.' qualifier to access simple_print. This qualifier tells the interpreter where to look for the attribute simple_print. Example Code 5.1 uses the import funtion to get the module_5 module, and runs the function simple_print.

Code Example 5.1:


#!/usr/bin/python # Print the required header that tells the browser how to render the text. print "Content-Type: text/plain\n\n" # Import the outside module. import module_5 # Call the 'simple_print' function using a qualifier. module_5.simple_print("This is printing made hard.")

Notice that the '.' qualifier tells the interpreter in module_5.simple_print("This is printing made hard.") to search for simple_print in module module_5 and send to it the parameter "This is printing made hard.". Note to C++ and Java Programmers Programmers used to information hiding and encapsulation should be warned that Python does not separate those variables that should and should not be visible outside the module. In short, Python does not provide a "private" or "protected" mechanism. Information hiding in Python is a programming convention and is not enforced by the language itself [2: 137]. To Lesson 6 ...

Lesson 6: Classes in Python


Classes are the way to develop object-oriented programming (OOP) in Python. Classes allow programmers to generate new objects in the Python language, as well as specialize, or inherit from, more general objects. In Python, the reserved word class allows programmers to create a new object type with special values and properties. Each class declaration creates a new instance with its own namespace [4, 2: 151 - 153]. To help clear up a very foggy aspect of OOP, let's look at an example.

simple_data_class.py:
# Define the class object class simple_data: # Define member functions def set_name(self, info): self.name = info def display_name(self): print self.name In Python, the reserved word self is similar to this in C++. The word self refers to the instance under operation. Rather than passing the object as a parameter, the word self refers to the object on which the '.' qualifier operates (in Code Example 6.1, store and item). Code Example 6.1 demonstrates the use of the simple_data class. This example also uses the reserved word from, which when coupled with the import function allows a client to select a specific class from a module.

Code Example 6.1:


#!/usr/bin/python # Print the required header that tells the browser how to render the text. print "Content-Type: text/plain\n\n" # Import the outside class. from simple_data_class import simple_data # Use default constructors to create 'simple_data' objects.

store = simple_data() item = simple_data() # Assign them values. store.set_name("Super Store") item.set_name("Month supply of tissue") # Print the values. store.display_name() item.display_name() Suppose we wanted to make a special version of simple_data that has a different version of display_name. This can be accomplished through inheritence. As shown in still_simple_data.py, the class definition syntax is much the same, except we note the class we wish to inhert from within parenthesis. still_simple_data objects retain the set_name member function from the simple_data class, but now they have their own version of print [2: 154 - 155].

still_simple_data_class.py:
# Define the class object class simple_data: # Define member functions def set_name(self, info): self.name = info def display_name(self): print self.name # Define a subclass object class still_simple_data(simple_data): # Define its own member function version of display_name def display_name(self): print "The name is:", self.name Code Example 6.2 shows both classes in action.

Code Example 6.2:


#!/usr/bin/python # Print the required header that tells the browser how to render the text. print "Content-Type: text/plain\n\n" # Import all(*) exports from the outside class. from still_simple_data_class import * # Use default constructors to create objects. store = simple_data() item = still_simple_data() # Assign them values. store.set_name("Super Store") item.set_name("Month supply of tissue") # Use superclass definition # Print the values.

store.display_name() item.display_name() # Use subclass definition Although the module and class examples in this tutorial are quite trivial, the power these features add to the language is very important. Modules and classes make Python extremely extensible. As long as the external interface to a class is kept constant, the underlying implementation can be reworked for future needs. This property of the language is invaluable in large-scale projects. To Lesson 7 ...

Lesson 7: The CGI module


The most common form of CGI programming handles interaction between user input in an HTML form and a database. HTML forms consist of several input fields, each given a key identifier, and a submit button that sends the data in a query string. Fortunately, the built-in Python CGI module parses this information in a class called cgi. The most useful member of this cgi class is the FieldStorage attribute. It returns the values of all the form fields in a object similar to the dictionary type.[4, 2: 276]. The Official Python Website has a complete description of the CGI module. Code Example 7.1 demonstrates a simple use of the cgi class.

Code Example 7.1:


#!/usr/bin/python # Import the CGI module import cgi # Required header that tells the browser how to render the HTML. print "Content-Type: text/html\n\n" # Define function to generate HTML form. def generate_form(): print "<HTML>\n" print "<HEAD>\n" print "\t<TITLE>Info Form</TITLE>\n" print "</HEAD>\n" print "<BODY BGCOLOR = white>\n" print "\t<H3>Please, enter your name and age.</H3>\n" print "\t<TABLE BORDER = 0>\n" print "\t\t<FORM METHOD = post ACTION = \ \"example_7.1.cgi\">\n" print "\t\t<TR><TH>Name:</TH><TD><INPUT type = text \ name = \"name\"></TD><TR>\n" print "\t\t<TR><TH>Age:</TH><TD><INPUT type = text name = \ \"age\"></TD></TR>\n" print "\t</TABLE>\n" print "\t<INPUT TYPE = hidden NAME = \"action\" VALUE =\

\"display\">\n" print "\t<INPUT TYPE = submit VALUE = \"Enter\">\n" print "\t</FORM>\n" print "</BODY>\n" print "</HTML>\n" # Define function display data. def display_data(name, age): print "<HTML>\n" print "<HEAD>\n" print "\t<TITLE>Info Form</TITLE>\n" print "</HEAD>\n" print "<BODY BGCOLOR = white>\n" print name, ", you are", age, "years old." print "</BODY>\n" print "</HTML>\n" # Define main function. def main(): form = cgi.FieldStorage() if (form.has_key("action") and form.has_key("name") \ and form.has_key("age")): if (form["action"].value == "display"): display_data(form["name"].value, form["age"].value) else: generate_form() # Call main function. main() Notice that several key features have been introduced in this example. First, in pink, the ContentType has been changed from text to html. Also, in pink, the ends of five lines each have a '\'. This '\' allows statements to wrap to a second line without affecting the indentation scheme of Python. In the example above, we use attributes (FieldStorage, has_key, and value) of the cgi class and the '.' qualifier to access the data sent by the HTML form. Since the program was relatively long, we divided the code into separate functions, including a main() function. The program works in a recursive fashion by calling itself in the HTML POST form command. Until the form is completed, the program calls generate_form. Once all the if statement conditions are met, the data is displayed. Login Management and Security Retrieving data from HTML fields is useful, but the combination of logging-in users and providing a small level of security can really show the benefits of CGI. In the example below, we demonstrate a basic method of password protection. The program uses the unix_md5_crypt() function that takes a password and encryption salt as parameters. It is located in the module md5crypt.py available from sabren.com. In Code Example 7.2, the usernames and encrypted passwords are stored in the file passwords.txt. An entered password is encrypted and tested against the first 20 letters of the encrypted password from the file (Evidently, there is a length limit on string comparisons). Note that the sys and string modules are imported to manipulate the passwords.txt file and the strings read from the file. For our example, ab is used as the encryption salt. The correct username is Python, and the correct password is Tutorial.

Code Example 7.2:

#!/usr/bin/python # Import the CGI, string, sys, and md5crypt modules import cgi, string, sys, md5crypt # Required header that tells the browser how to render the HTML. print "Content-Type: text/html\n\n" # Define function to generate HTML form. def generate_form(): print "<HTML>\n" print "<HEAD>\n" print "\t<TITLE>Info Form</TITLE>\n" print "</HEAD>\n" print "<BODY BGCOLOR = white>\n" print "\t<H3>Please, enter your username and password.</H3>\n" print "\t<TABLE BORDER = 0>\n" print "\t\t<FORM METHOD = post ACTION = \ \"example_7.2.cgi\">\n" print "\t\t<TR><TH>Username:</TH><TD><INPUT TYPE = text \ NAME = \"username\"></TD><TR>\n" print "\t\t<TR><TH>Password:</TH><TD><INPUT \ TYPE = password NAME = \"password\"></TD></TR>\n" print "\t</TABLE>\n" print "\t<INPUT TYPE = hidden NAME = \"action\" VALUE =\ \"display\">\n" print "\t<INPUT TYPE = submit VALUE = \"Enter\">\n" print "\t</FORM>\n" print "</BODY>\n" print "</HTML>\n" # Define function to test the password. def test(id, passwd): passwd_file = open('passwords.txt', 'r') line = passwd_file.readline() passwd_file.close() combo = string.split(line, ":") encrypted_pw = md5crypt.unix_md5_crypt(passwd, 'ab') if ((id == combo[0]) and (encrypted_pw[0:20] == combo[1][0:20])): return "passed" else: return "failed" # Define function display_page. def display_page(result): print "<HTML>\n" print "<HEAD>\n" print "\t<TITLE>Info Form</TITLE>\n" print "</HEAD>\n" print "<BODY BGCOLOR = white>\n" if (result == "passed"):

print "You entered the correct combo.\n" else: print "You entered the incorrect combo.\n" print "</BODY>\n" print "</HTML>\n" # Define main function. def main(): form = cgi.FieldStorage() if (form.has_key("action") and form.has_key("username") \ and form.has_key("password")): if (form["action"].value == "display"): result = test(form["username"].value, form["password"].value) display_page(result) else: generate_form() # Call main function. main()

Maintaining Sessions Once users have logged into your site, keeping track of their requests and associating the correct request with the correct user poses a challenging problem. HTML does not provide a method of retaining state. The status of a user, whether logged in or not, must be transferred from program to program (or recursively back to the same program). Assigning each user with a random session key can fix this problem. The session key, a random string or number, can be used to correlate users and their session data. After the key is established at login, this user data/key pairing can be stored in a file and accessed by subsequent CGI program requests. After the user logs out of the site, the pairing should be erased so that future logins are not confused with those of the past. Additionally, for security reasons, the session key file should be kept safely away from public view. Code Example 7.3 adds to the previous examples by allowing a user to remain logged in. Each time the program executes it tests for the session key and finds its owner.

Code Example 7.3:


#!/usr/bin/python # Import the CGI, string, sys, and md5crypt modules import cgi, string, sys, md5crypt # Required header that tells the browser how to render the HTML. print "Content-Type: text/html\n\n" # Define function to generate HTML form. def generate_form(): print "<HTML>\n" print "<HEAD>\n" print "\t<TITLE>Info Form</TITLE>\n" print "</HEAD>\n" print "<BODY BGCOLOR = white>\n" print "\t<H3>Please, enter your username and

password.</H3>\n" print "\t<TABLE BORDER = 0>\n" print "\t\t<FORM METHOD = post ACTION = \ \"example_7.2.cgi\">\n" print "\t\t<TR><TH>Username:</TH><TD><INPUT TYPE = text \ NAME = \"username\"></TD><TR>\n" print "\t\t<TR><TH>Password:</TH><TD><INPUT \ TYPE = password NAME = \"password\"></TD></TR>\n" print "\t</TABLE>\n" print "\t<INPUT TYPE = hidden NAME = \"action\" VALUE =\ \"display\">\n" print "\t<INPUT TYPE = submit VALUE = \"Enter\">\n" print "\t</FORM>\n" print "</BODY>\n" print "</HTML>\n" # Define function to test the password. def test(id, passwd): passwd_file = open('passwords.txt', 'r') line = passwd_file.readline() passwd_file.close() combo = string.split(line, ":") encrypted_pw = md5crypt.unix_md5_crypt(passwd, 'ab') if ((id == combo[0]) and (encrypted_pw[0:20] == combo[1][0:20])): return "passed" else: return "failed" # Define function to create a session. def create_session(id): session_file = open('sessions.txt', 'w') # In practice, use the random module for key value. session_key = "a12bc78z" session_file.write(session_key+":"+id) session_file.close() return session_key # Define a function to return username. def fetch_username(key): session_file = open('sessions.txt', 'r') # In practice, search file for correct key. line = session_file.readline() session_file.close() pair = string.split(line, ":") return pair[1] # Define function to delete a session. def delete_session(id): session_file = open('sessions.txt', 'w') # In practice, search the file for the correct key. # In our example, we just erase the only line in the file. session_file.write(" ")

session_file.close() # Define function display_page. def display_page(result, id, session_key = 0): print "<HTML>\n" print "<HEAD>\n" print "\t<TITLE>Info Form</TITLE>\n" print "</HEAD>\n" print "<BODY BGCOLOR = white>\n" if (result == "passed"): if (session_key == 0): session_key = create_session(id) print id, , you are logged in with key:", session_key, "\n" print "\t\t<FORM METHOD = post ACTION = \ \"example_7.3.cgi\">\n" print "\t\t<INPUT TYPE = \"hidden\" NAME = \ \"session_key\" VALUE =\", session_key, ">\n" print "\t\t<INPUT TYPE = \"submit\" \ VALUE = \"Stay Logged In.\"></FORM>\n" print "\t\t<FORM METHOD = post ACTION = \ \"example_7.3.cgi\">\n" print "\t\t<INPUT TYPE = \"hidden\" NAME = \ \"session_key\" VALUE =", session_key, ">\n" print "\t\t<INPUT TYPE = \"hidden\" NAME =\ \"logout\" VALUE = \"logout\" >\n" print "\t\t<INPUT TYPE = \"submit\" \ VALUE = \"Logout.\"></FORM>\n" else: print "You entered the incorrect combo.\n" print "</BODY>\n" print "</HTML>\n" # Define main function. def main(): form = cgi.FieldStorage() if (form.has_key("session_key")): if (form.has_key("logout")): delete_session(form["session_key"].value) generate_form() else: u_id = fetch_username(form["session_key"].value) display_page("passed", u_id, form["session_key"].value) elif (form.has_key("action") and form.has_key("username") \ and form.has_key("password")): if (form["action"].value == "display"): result = test(form["username"].value, form["password"].value) display_page(result, form["username"].value) else: generate_form() # Call main function. main()

Correlating Multiple Sessions While managing a single session adds to the functionality of a site, correlating these sessions for repeat visitors presents another problem of user account management. The module Cookie.py offers the ability for Python CGI programs to store HTTP cookies on the clients' local machines. Cookies are persistent data files stored on the client machine through the Web browser. The Cookie.py module writes "Set-Cookie" headers and parses the HTTP-COOKIE environment variable. These options create a more standardized method of dealing with client tracking and data retrieval. As a warning, most Web browsers allow users to reject the use of cookies, and this can break code written with dependencies on cookies. Code Example 7.4 shows the syntax for setting and reading a simple cookie.

Code Example 7.4:


#!/usr/bin/python # Import the cgi, os, and Cookie modules. import cgi, os, Cookie # Define function to set a cookie. def set_client_Cookie(): # Create a Cookie object. a_cookie = Cookie.SmartCookie() # Assign the cookie a value. a_cookie["user"] = "Python" # Required header that tells the browser how to render the HTML. print "Content-Type: text/html" # Send the cookie back to the client. print a_cookie, "\n\n" # Print the cookie value. print "<HTML><BODY>" print a_cookie["user"].value, "user cookie set.\n" print "<FORM METHOD = post ACTION = \"example_7.4.cgi\">\n" print "<INPUT TYPE = \"hidden\" NAME = \ \"set\" VALUE =\"yes\">\n" print "<INPUT TYPE = \"submit\" VALUE = \"Go\"></FORM>\n" print "</BODY></HTML>\n" # Define function to read a cookie. def read_client_Cookie(): # Create a Cookie object. a_cookie = Cookie.SmartCookie( os.environ.get("HTTP_COOKIE", "") ) # Assign the variable a cookie value. cookie_val = a_cookie["user"].value # Required header that tells the browser how to render the HTML.

print "Content-Type: text/html\n\n" # Print the cookie value. print "<HTML><BODY>" print cookie_val, "user cookie read from client.\n" print "</BODY></HTML>\n" # Define main function. def main(): form = cgi.FieldStorage() if (form.has_key("set")): if (form["set"].value == "yes"): read_client_Cookie() else: set_client_Cookie() # Call main function. main() While the HTML generation may become clearer with HTML modules and the data storage better with databases, the above examples exhibit the core of CGI programming.

To Lesson 8 ...

Lesson 8: The Python DB-API, Version 1.0


Most Web sites require large-scale data warehousing and data mining. This feat is nearly impossible without the use of a relational database backend. Additionally, many of the commercially available interfaces to leading database engines are extremely costly. This cost can be avoided by employing the Python Database Application Program Interface (DB-API) modules to handle Structured Query Language (SQL) requests to various database engines. The DB-API provides a standard Python interface to most commercial, freeware, and shareware databases. Therefore, there exists a single, uniform interface format to learn, and modifying the front-end code to work with a different database product requires only minor changes [5]. The first step in using a DB-API module is to import the correct database module and create an object to represent the database connection. By convention, all DB-API compliant database modules have names ending with the letters 'db' (i.e., oracledb, informixdb, mysqldb, and soliddb). The correct syntax for this process is described below.

Code Example 8.1:


# Import the module. import oracledb # Create a connection. db = oracledb.oracledb("db_username/password@db_host") # Close connection when finished. db.close() In the example above, the words in pink should be substituted with your username, password, and host. Note that this connection string format is specific to the oracledb module. Each DB-API

compliant module has a different connection string format, and you should check the documentation to your specific module. Simple SQL Queries After you have established connection with the database, you should create a cursor object to act as a handle for SQL queries. This cursor handle facilitates the retrieval of table rows from the database. The most basic cursor member functions are execute("some_SQL_statement"), fetchone(), and fetchall(). The execute() function takes the SQL statement (most commonly a "select", "insert", or "update" statement) to be performed. The fetchone() function returns a single row that matches the execute() query. The return value is a Python tuple data type. The fetchall() function returns all rows that match the execute() query. This function returns a list data type of tuple data types. Code Example 8.2 demonstrates the proper syntax for the cursor functions. Again, the words in pink should be substituted with items specific to your database.

Code Example 8.2:


# Import the module. import oracledb # Create a connection. db = oracledb.oracledb("db_username/password@db_host") # Create a cursor. cursor = db.cursor() # Query the database. cursor.execute('select * from a_table') # Return a single row. single_row = cursor.fetchone() # Return every matching row. list_of_rows = cursor.fetchall() # Close connection when finished. db.close() Transactions Some situations require updates to several dependent database tables. For example, imagine a CGI program that transfers money from one bank account to another. The tuples, account balances in this case, must be updated "simultaneously." If one account tuple is subtracted by the transfer amount, and a program error or network failure causes the second account not to be updated, money is "lost." A transaction is a group of commands, where either all or none of the commands are executed. A partial execution would leave the database in an inconsistent state [5]. Python provides the commit() function for the DB-API compliant modules. When an "insert" or "update" SQL command is issued, the db.commit() function commits all the statements made by the cursor. The rollback() function discards the cursor statements. Some database engines do not support this feature; check your documentation.

Potrebbero piacerti anche