An odds-and-ends Workbook¶
This workbook / cookbook of recipes is still very much under construction.
The Five Strands of Proficiency¶
This was an important study commissioned by the President in the USA. It looked at what was needed for students to become proficient in maths.
But it is also an amazingly accurate fit for what we need for proficiency in Computer Science, or even for proficiency in playing Jazz!
Procedural Fluency: Learn the syntax. Learn to type. Learn your way around your tools. Learn and practice your scales. Learn to rearrange formulae.
Conceptual Understanding: Understand why the bits fit together like they do.
Strategic Competence: Can you see what to do next? Can you formulate this word problem into your notation? Can you take the music where you want it to go?
Adaptive Reasoning: Can you see how to change what you’ve learned for this new problem?
- A Productive Disposition: We need that Can Do! attitude!
You habitually think it is worthwhile studying this stuff.
You are diligent and disciplined enough to grind through the tough stuff, and to put in your practice hours.
You develop a sense of efficacy — that you can make things happen!
Check out http://mason.gmu.edu/~jsuh4/teaching/strands.htm, or Kilpatrick’s book at http://www.nap.edu/openbook.php?isbn=0309069955
Sending Email¶
Sometimes it is fun to do powerful things with Python — remember that part of the “productive disposition” we saw under the five threads of proficiency included efficacy — the sense of being able to accomplish something useful. Here is a Python example of how you can send email to someone.
1import smtplib, email.mime.text
2
3me = "joe@my.org.com" # Put your own email here
4fred = "fred@his.org.com" # And fred's email address here
5your_mail_server = "mail.my.org.com" # Ask your system administrator
6
7# Create a text message containing the body of the email.
8# You could read this from a file, of course.
9msg = email.mime.text.MIMEText("""Hey Fred,
10
11I'm having a party, please come at 8pm.
12Bring a plate of snacks and your own drinks.
13
14Joe""" )
15
16msg["From"] = me # Add headers to the message object
17msg["To"] = fred
18msg["Subject"] = "Party on Saturday 23rd"
19
20# Create a connection to your mail server
21svr = smtplib.SMTP(your_mail_server)
22response = svr.sendmail(me, fred, msg.as_string()) # Send message
23if response != {}:
24 print("Sending failed for ", response)
25else:
26 print("Message sent.")
27
28svr.quit() # Close the connection
In the context of the course, notice how we use the two objects in this program: we create a message object on line 9, and set some attributes at lines 16-18. We then create a connection object at line 21, and ask it to send our message.
Write your own Web Server¶
Python is gaining in popularity as a tool for writing web applications. Although one will probably use Python to process requests behind a web server like Apache, there are powerful libraries which allow you to write your own stand-alone web server in a couple of lines. This simpler approach means that you can have a test web server running on your own desktop machine in a couple of minutes, without having to install any extra software.
In this cookbook example we use the wsgi (“wizz-gee”) protocol: a modern way
of connecting web servers to code that runs to provide the services.
See http://en.wikipedia.org/wiki/Web_Server_Gateway_Interface for more on wsgi.
1from codecs import latin_1_encode
2from wsgiref.simple_server import make_server
3
4def my_handler(environ, start_response):
5 path_info = environ.get("PATH_INFO", None)
6 query_string = environ.get("QUERY_STRING", None)
7 response_body = "You asked for {0} with query {1}".format(
8 path_info, query_string)
9 response_headers = [("Content-Type", "text/plain"),
10 ("Content-Length", str(len(response_body)))]
11 start_response("200 OK", response_headers)
12 response = latin_1_encode(response_body)[0]
13 return [response]
14
15httpd = make_server("127.0.0.1", 8000, my_handler)
16httpd.serve_forever() # Start the server listening for requests
When you run this, your machine will listen on port 8000 for requests. (You may have to tell your firewall software to be kind to your new application!)
In a web browser, navigate to http://127.0.0.1:8000/catalogue?category=guitars. Your browser should get the response
You asked for /catalogue with query category=guitars
Your web server will keep running until you interrupt it (Ctrl+F2 if you are using PyScripter).
The important lines 15 and 16 create a web server on the local machine,
listening at port 8000. Each incoming html request causes the server to
call my_handler which processes the request and returns the appropriate
response.
We modify the above example below: my_handler now
interrogates the path_info, and calls specialist functions to deal with
each different kind of incoming request.
(We say that my_handler dispatches the request to
the appropriate function.) We can easily add other more request cases:
1import time
2
3def my_handler(environ, start_response):
4 path_info = environ.get("PATH_INFO", None)
5 if path_info == "/gettime":
6 response_body = gettime(environ, start_response)
7 elif path_info == "/classlist":
8 response_body = classlist(environ, start_response)
9 else:
10 response_body = ""
11 start_response("404 Not Found", [("Content-Type", "text/plain")])
12
13 response = latin_1_encode(response_body)[0]
14 return [response]
15
16def gettime(env, resp):
17 html_template = """<html>
18 <body bgcolor='lightblue'>
19 <h2>The time on the server is {0}</h2>
20 <body>
21 </html>
22 """
23 response_body = html_template.format(time.ctime())
24 response_headers = [("Content-Type", "text/html"),
25 ("Content-Length", str(len(response_body)))]
26 resp("200 OK", response_headers)
27 return response_body
28
29def classlist(env, resp):
30 return # Will be written in the next section!
Notice how gettime returns an (admittedly simple) html document which is
built on the fly by using format to substitute content into a
predefined template.
Using a Database¶
Python has a library for using the popular and lightweight sqlite database. Learn more about this self-contained, embeddable, zero-configuration SQL database engine at http://www.sqlite.org.
Firstly, we have a script that creates a new database, creates a table, and stores some rows of test data into the table: (Copy and paste this code into your Python system.)
1import sqlite3
2
3# Attach to (or create) the database
4connection = sqlite3.connect("c:\studentRecords.db")
5
6# Create a new table with three fields
7cursor = connection.cursor()
8cursor.execute("""CREATE TABLE StudentSubjects
9 (studentName text, year integer, subject text)""")
10
11print("Database table StudentSubjects has been created.")
12
13# Create some testdata, and write rows to the table.
14test_data = [
15 ("John", 2012, ["CompSci", "Physics"]),
16 ("Vusi", 2012, ["Maths", "CompSci", "Stats"]),
17 ("Jess", 2011, ["CompSci", "Accounting", "Economics", "Management"]),
18 ("Sarah", 2011, ["InfSys", "Accounting", "Economics", "CommLaw"]),
19 ("Zuki", 2012, ["Sociology", "Economics", "Law", "Stats", "Music"])]
20
21for (student, yr, subjects) in test_data:
22 for subj in subjects:
23 t = (student, yr, subj)
24 cursor.execute("INSERT INTO StudentSubjects VALUES (?,?,?)", t)
25
26connection.commit()
27
28# Now verify that we did write the data
29cursor.execute("SELECT COUNT(*) FROM StudentSubjects")
30result = cursor.fetchall()
31numrecs = result[0][0]
32cursor.close()
33
34print("StudentSubjects table now has {0} rows of data.".format(numrecs))
We get this output:
Database table StudentSubjects has been created.
StudentSubjects table now has 18 rows of data.
Our next recipe adds to our web browser from the previous section. We’ll
allow a query like classlist?subject=CompSci&year=2012 and show how
our server can extract the arguments from the query string, query the database,
and send the rows back to the browser as a formatted table within an html page. We’ll start
with two new imports to get access to sqlite3 and cgi, a library which
helps us parse forms and query strings that are sent to the server:
1import sqlite3
2import cgi
Now we replace the stub function classlist with a handler that can do what we need:
1classlistTemplate = """<html>
2<body bgcolor='lightgreen'>
3 <h2>Students taking {0} during {1}:</h2>
4 <table border=3 cellspacing=2 cellpadding=2>
5{2}
6 </table>
7<body>
8</html>
9"""
10
11def classlist(env, resp):
12
13 # Parse the field value from the query string (or from a submitted form)
14 # In a real server you'd want to check thay they were present!
15 the_fields = cgi.FieldStorage(environ = env)
16 subj = the_fields["subject"].value
17 year = the_fields["year"].value
18
19 # Attach to the database, build a query, fetch the rows.
20 connection = sqlite3.connect("c:\studentRecords.db")
21 cursor = connection.cursor()
22 cursor.execute("SELECT * FROM StudentSubjects WHERE subject=? AND year=?",
23 (subj, year))
24 result = cursor.fetchall()
25 # Build the html rows for the table
26 table_rows = ""
27 for (sn, yr, subj) in result:
28 table_rows += " <tr><td>{0}<td>{1}<td>{2}\n". format(sn, yr, subj)
29
30 # Now plug the headings and data into the template, and complete the response
31 response_body = classlistTemplate.format(subj, year, table_rows)
32 response_headers = [("Content-Type", "text/html"),
33 ("Content-Length", str(len(response_body)))]
34 resp("200 OK", response_headers)
35 return response_body
When we run this and navigate to http://127.0.0.1:8000/classlist?subject=CompSci&year=2012 with a browser, we’ll get output like this:
It is unlikely that we would write our own web server from scratch. But the beauty of this
approach is that it creates a great test environment for working with server-side applications
that use the wsgi protocols. Once our code is ready, we can deploy it behind a web
server like Apache which can interact with our handlers using wsgi.