Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
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.
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.
The code examples below demonstrate various assignment methods and results.
# 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.
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.
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 ...
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!"
print "Finished."
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.
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 ...
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.
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 ...
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.
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.
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 ...
\"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.
#!/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.
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.
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 ...
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.