program in python - full circledl.fullcirclemagazine.org/issuepy01_en.pdf · programming series...

42
PROGRAMMING SERIES SPECIAL EDITION PROGRAM PROGRAM IN PYTHON IN PYTHON Volume Volume One One Full Circle Magazine is neither affiliated, with nor endorsed by, Canonical Ltd.

Upload: truongthuan

Post on 08-Feb-2018

229 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: PROGRAM IN PYTHON - Full Circledl.fullcirclemagazine.org/issuePY01_en.pdf · PROGRAMMING SERIES SPECIAL EDITION PROGRAM IN PYTHON Volume One Full Circle Magazine is neither affiliated,

PROGRAMMING SERIES SPECIAL EDITION

PROGRAMPROGRAM IN PYTHONIN PYTHON Volume Volume OneOne

Full Circle Magazine is neither affiliated, with nor endorsed by, Canonical Ltd.

Page 2: PROGRAM IN PYTHON - Full Circledl.fullcirclemagazine.org/issuePY01_en.pdf · PROGRAMMING SERIES SPECIAL EDITION PROGRAM IN PYTHON Volume One Full Circle Magazine is neither affiliated,

Full Circle Magazine Specials

Full Circle Magazine

The articles contained in this magazine are released under the Creative Commons Attribution-Share Alike 3.0Unported license. This means you can adapt, copy, distribute and transmit the articles but only under the following conditions:

You must attribute the work to the original author in some way (at least a name, email or URL) and to this magazine by name ('full circle magazine') and the URL www.fullcirclemagazine.org (but not attribute the article(s) in any way that suggests that they endorse you or your use of the work). If you alter, transform, or build upon this work, you must distribute the resulting work under the same, similar or a compatible license.Full Circle Magazine is entirely independent of Canonical, the sponsor of Ubuntu projects and the views and opinions in the magazine should in no way be assumed to have Canonical endorsement.

Please note: this Special Edition is provided with absolutely no warranty whatsoever; neither the contributors nor Full Circle Magazine accept any responsibility or liability for loss or damage resulting from readers choosing to apply this content to theirs or others computers and equipment.

About Full Circle

Full Circle is a free, independent, magazine dedicated to the Ubuntu family of Linux operating systems. Each month, it contains helpful how-to articles and reader- submitted stories.

Full Circle also features a companion podcast, the Full Circle Podcast which covers the magazine, along with other news of interest.

Welcome to another 'single-topic special'In response to reader requests, we are assembling the content of some of our serialised articles into dedicated editions.

For now, this is a straight reprint of the series 'Programming in Python', Parts 1-8 from issues #27 through #34; nothing fancy, just the facts.

Please bear in mind the original publication date; current versions of hardware and software may differ from those illustrated, so check your hardware and software versions before attempting to emulate the tutorials in these special editions. You may have later versions of software installed or available in your distributions' repositories.

Enjoy!

Find Us

Website: http://www.fullcirclemagazine.org/

Forums: http://ubuntuforums.org/forumdisplay.php?f=270

IRC: #fullcirclemagazine on chat.freenode.net

Editorial Team

Editor: Ronnie Tucker (aka: RonnieTucker) [email protected]

Webmaster: Rob Kerfia (aka: admin / linuxgeekery- [email protected]

Podcaster: Robin Catling (aka RobinCatling) [email protected]

Communications Manager: Robert Clipsham (aka: mrmonday) - [email protected]

Page 3: PROGRAM IN PYTHON - Full Circledl.fullcirclemagazine.org/issuePY01_en.pdf · PROGRAMMING SERIES SPECIAL EDITION PROGRAM IN PYTHON Volume One Full Circle Magazine is neither affiliated,

full circle magazine #27 7 contents ^

HOW-TO Program In Python - Part 1

N/A

GraphicsDev Internet M/media System

HDDCD/DVD USB Drive Laptop Wireless

Among the manyprogramminglanguages currentlyavailable, Python is

one of the easiest to learn.Python was created in the late1980's, and has maturedgreatly since then. It comes pre-installed with most Linuxdistributions, and is often oneof the most overlooked whenpicking a language to learn.We'll deal with command-lineprogramming in this article. Ina future one, we'll play with GUI

(Graphical User Interface)programming. Let's jump rightin, creating a simpleapplication.

Our First ProgramUsing a text editor such as

gedit, let's type some code.Then we'll see what each linedoes and go from there.

Type the following 4 lines.

#!/usr/bin/env python

print 'Hello. I am a pythonprogram.'

name = raw_input("What isyour name? ")

print "Hello there, " + name+ "!"

That's all there is to it. Savethe file as hello.py whereveryou would like. I'd suggestputting it in your homedirectory in a folder namedpython_examples. This simpleexample shows how easy it isto code in Python. Before wecan run the program, we need

to set it to be executable. Dothis by typing

chmod +x hello.py

in the folder where you savedyour python file. Now let's runthe program.

greg@earth:~/python_examples$./hello.py

Hello. I am a pythonprogram.

What is your name? FerdBurphel

Hello there, Ferd Burphel!

greg@earth:~/python_examples$

That was simple. Now, let'slook at what each line of theprogram does.

#!/usr/bin/env python

This line tells the systemthat this is a python program,and to use the default pythoninterpreter to run the program.

print 'Hello. I am a pythonprogram.'

Simply put, this prints thefirst line "Hello. I am a pythonprogram." on the terminal.

name = raw_input("What isyour name? ")

This one is a bit morecomplex. There are two partsto this line. The first is name =,and the second israw_input("What is your name?"). We'll look at the second partfirst. The command raw_inputwill print out the prompt in theterminal ("What is your name?"), and then will wait for theuser (you) to type something(followed by {Enter}). Nowlet's look at the first part: name=. This part of the commandassigns a variable named"name". What's a variable?Think of a variable as a shoe-box. You can use a shoe-box tostore things -- shoes, computerparts, papers, whatever. To theshoe-box, it doesn't reallymatter what's in there -- it'sjust stored there. In this case, itstores whatever you type. Inthe case of my entry, I typedFerd Burphel. Python, in this

Page 4: PROGRAM IN PYTHON - Full Circledl.fullcirclemagazine.org/issuePY01_en.pdf · PROGRAMMING SERIES SPECIAL EDITION PROGRAM IN PYTHON Volume One Full Circle Magazine is neither affiliated,

full circle magazine #27 8 contents ^

PROGRAM IN PYTHON - PART 1instance, simply takes theinput and stores it in the"name" shoe-box for use laterin the program.

print "Hello there, " + name+ "!"

Once again, we are usingthe print command to displaysomething on the screen -- inthis case, "Hello there, ", pluswhatever is in the variable"name", and an exclamationpoint at the end. Here we areconcatenating or puttingtogether three pieces ofinformation: "Hello there",information in the variable"name", and the exclamationpoint.

Now, let's take a moment todiscuss things a bit moredeeply before we work on ournext example. Open a terminalwindow and type:

python

You should get somethinglike this:

greg@earth:~/python_examples$python

Python 2.5.2 (r252:60911,

Oct 5 2008, 19:24:49)

[GCC 4.3.2] on linux2

Type "help", "copyright","credits" or "license" formore information.

>>>

You are now in the pythonshell. From here, you can do anumber of things, but let's seewhat we got before we go on.The first thing you shouldnotice is the python version --mine is 2.5.2. Next, you shouldnotice a statement indicatingthat, for help, you should type"help" at the prompt. I'll let youdo that on your own. Now type:

print 2+2

and press enter. You'll get back

>>> print 2+24>>>

Notice that we typed theword "print" in lower case.What would happen if we typed"Print 2+2"? The response fromthe interpreter is this:

>>> Print 2+2File "<stdin>", line 1

Print 2+2

^SyntaxError: invalid syntax>>>

That's because the word"print" is a known command,while "Print" is not. Case isvery important in Python.

Now let's play with variablesa bit more. Type:

var = 2+2

You'll see that nothing muchhappens except Python returnsthe ">>>" prompt. Nothing iswrong. What we told Python todo is create a variable (shoe-box) called var, and to stickinto it the sum of "2+2". To seewhat var now holds, type:

print var

and press enter.

>>> print var4>>>

Now we can use var overand over again as the number4, like this:

>>> print var * 28>>>

If we type "print var" againwe'll get this:

>>> print var4>>>

var hasn't changed. It's stillthe sum of 2+2, or 4.

This is, of course, simpleprogramming for thisbeginner's tutorial. Complexitywill increase in subsequenttutorials. But now let's look atsome more examples ofvariables.

In the interpreter type:

>>> strng = 'The time hascome for all good men tocome to the aid of theparty!'

>>> print strng

The time has come for allgood men to come to the aidof the party!

>>>

You've created a variablenamed "strng" (short for string)containing the value 'The timehas come for all good men tocome to the aid of the party!'.From now on (as long as we are

Page 5: PROGRAM IN PYTHON - Full Circledl.fullcirclemagazine.org/issuePY01_en.pdf · PROGRAMMING SERIES SPECIAL EDITION PROGRAM IN PYTHON Volume One Full Circle Magazine is neither affiliated,

full circle magazine #27 9 contents ^

PROGRAM IN PYTHON - PART 1in this instance of theinterpreter), our strng variablewill be the same unless wechange it. What happens if wetry to multiply this variable by4?

>>> print strng * 4

The time has come for allgood men to come to the aidof the party!The time hascome for all good men tocome to the aid of theparty!The time has come forall good men to come to theaid of the party!The timehas come for all good men tocome to the aid of the party!

>>>

Well, that is not exactlywhat you would expect, is it? Itprinted the value of strng 4times. Why? Well, theinterpreter knew that strng wasa string of characters, not avalue. You can't perform mathon a string.

What if we had a variablecalled s that contained '4', asin the following:

>>> s = '4'>>> print s4

It looks as though s containsthe integer 4, but it doesn't.Instead it contains a stringrepresentation of 4. So, if wetype 'print s * 4' we get...

>>> print s*44444>>>

Once again, the interpreterknows that s is a string, not anumerical value. It knows thisbecause we enclosed thenumber 4 with single quotes,making it a string.

We can prove this by typingprint type(s) to see what thesystem thinks that variabletype is.

>>> print type(s)<type 'str'>>>>

Confirmation. It's a stringtype. If we want to use this asa numerical value, we could dothe following:

>>> print int(s) * 416>>>

The string (s), which is '4',has now been converted to an

integer and then multiplied by4 to give 16.

You have now beenintroduced to the printcommand, the raw_inputcommand, assigning variables,and the difference betweenstrings and integers.

Let's go a bit further. In thePython Interpreter, type quit()to exit back to the commandprompt.

Simple For LoopNow, let's explore a simple

programming loop. Go back tothe text editor and type thefollowing program.

#! /usr/bin/env python

for cntr in range(0,10):

print cntr

Be sure to tab the "printcntr" line. This is important.Python doesn't useparentheses "(" or curly braces"{" as do other programminglanguages to show codeblocks. It uses indentationsinstead.

Save the program as"for_loop.py". Before we try torun this, let's talk about what afor loop is.

A loop is some code thatdoes a specified instruction, orset of instructions, a number oftimes. In the case of ourprogram, we loop 10 times,printing the value of thevariable cntr (short forcounter). So the command inplain English is "assign thevariable cntr 0, loop 10 timesprinting the variable cntrcontents, add one to cntr anddo it all over again. Seemssimple enough. The part of thecode "range(0,10)" says startwith 0, loop until the value ofcntr is 10, and quit.

Now, as before, do a

chmod +x for_loop.py

and run the program with

./for_loop.py

in a terminal.

greg@earth:~/python_examples$./for_loop.py01

Page 6: PROGRAM IN PYTHON - Full Circledl.fullcirclemagazine.org/issuePY01_en.pdf · PROGRAMMING SERIES SPECIAL EDITION PROGRAM IN PYTHON Volume One Full Circle Magazine is neither affiliated,

full circle magazine #27 10 contents ^

PROGRAM IN PYTHON - PART 123456789greg@earth:~/python_examples$

Well, that seems to haveworked, but why does it countup to only 9 and then stop.Look at the output again. Thereare 10 numbers printed,starting with 0 and ending with9. That's what we asked it todo -- print the value of cntr 10times, adding one to thevariable each time, and quit assoon as the value is 10.

Now you can see that, whileprogramming can be simple, itcan also be complex, and youhave to be sure of what youask the system to do. If youchanged the range statementto be "range(1,10)", it wouldstart counting at 1, but end at9, since as soon as cntr is 10,the loop quits. So to get it toprint "1,2,3,4,5,6,7,8,9,10", weshould use range(1,11) - sincethe for loop quits as soon asthe upper range number isreached.

Also notice the syntax of thestatement. It is "for variable inrange(start value,end value):"The ":" says, we are starting ablock of code below thatshould be indented. It is veryimportant that you rememberthe colon ":", and to indent thecode until the block is finished.

If we modified our programto be like this:

#! /usr/bin/env python

for cntr in range(1,11):

print cntr

print 'All Done'

We would get an output of...

greg@earth:~/python_examples$./for_loop.py12345678910All Donegreg@earth:~/python_examples$

Make sure your indentationis correct. Remember,

indentation shows the blockformatting. We will get intomore block indentationthoughts in our next tutorial.

That's about all for thistime. Next time we'll recap andmove forward with morepython programminginstructions. In the meantime,you might want to considerinstalling a python specificeditor like Dr. Python, or SPE(Stani's Python Editor), both ofwhich are available throughSynaptic.

is owner of, a

consulting company in Aurora,Colorado, and has beenprogramming since 1972. Heenjoys cooking, hiking, music,and spending time with hisfamily.

Page 7: PROGRAM IN PYTHON - Full Circledl.fullcirclemagazine.org/issuePY01_en.pdf · PROGRAMMING SERIES SPECIAL EDITION PROGRAM IN PYTHON Volume One Full Circle Magazine is neither affiliated,

full circle magazine #28 7 contents ^

HOW-TO Program In Python - Part 2

FCM#27 - Python Part 1

GraphicsDev Internet M/media System

HDDCD/DVD USB Drive Laptop Wireless

In the last installment, welooked at a simpleprogram using raw_inputto get a response from the

user, some simple variabletypes, and a simple loop usingthe "for" statement. In thisinstallment, we will delve moreinto variables, and write a fewmore programs.

Let's look at another type ofvariable called lists. In otherlanguages, a list would beconsidered an array. Goingback to the analogy of shoe-boxes, an array (or list) wouldbe a number of boxes all gluedside-by-side holding like items.For example, we could storeforks in one box, knives inanother, and spoons inanother. Let's look at a simplelist. An easy one to picturewould be a list of monthnames. We would code it likethis...

months =['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oc

t','Nov','Dec']

To create the list, we bracketall the values with squarebrackets ( '[' and ']' ). We havenamed our list 'months'. To useit, we would say something likeprint months[0] or months[1](which would print 'Jan' or'Feb'). Remember that wealways count from zero. To findthe length of the list, we canuse:

print len(months)

which returns 12.

Another example of a listwould be categories in acookbook. For example...

categories = ['Maindish','Meat','Fish','Soup','Cookies']

Then categories[0] would be'Main dish', and categories[4]would be 'Cookies'. Prettysimple again. I'm sure you canthink of many things that youcan use a list for.

Up to now, we have createda list using strings as theinformation. You can alsocreate a list using integers.Looking back at our monthslist, we could create a listcontaining the number of daysin each one:

DaysInMonth =[31,28,31,30,31,30,31,31,30,31,30,31]

If we were to printDaysInMonth[1] (for February)we would get back 28, which isan integer. Notice that I madethe list name DaysInMonth.Just as easily, I could haveused 'daysinmonth' or just 'X'...but that is not quite so easy toread. Good programmingpractices suggest (and this issubject to interpretation) thatthe variable names are easy tounderstand. We'll get into thewhys of this later on. We'll playwith lists some more in a littlewhile.

Before we get to our nextsample program, let's look at afew other things about Python.

I received an email from DavidTurner who suggested that usingthe Tab-key for indentation of codeis somewhat misleading as someeditors may use more, or less, thanfour spaces per indent. This iscorrect. Many Python programmers(myself included) save time bysetting the tab key in their editor tofour spaces. The problem is,however, that someone else'seditor may not have the samesetting as yours, which could leadto ugly code and other problems.So, get into the habit of usingspaces rather than the Tab-key.

Page 8: PROGRAM IN PYTHON - Full Circledl.fullcirclemagazine.org/issuePY01_en.pdf · PROGRAMMING SERIES SPECIAL EDITION PROGRAM IN PYTHON Volume One Full Circle Magazine is neither affiliated,

full circle magazine #28 8 contents ^

PROGRAM IN PYTHON - PART 2

We briefly discussed stringsin Part 1. Let's look at string abit closer. A string is a series ofcharacters. Not much morethan that. In fact, you can lookat a string as an array ofcharacters. For example if weassign the string 'The time hascome' to a variable namedstrng, and then wanted toknow what the secondcharacter would be, we couldtype:

strng = 'The time has come'print strng[1]

The result would be 'h'.Remember we always countfrom 0, so the first characterwould be [0], the second wouldbe [1], the third would be [2],and so on. If we want to findthe characters starting atposition 4 and going throughposition 8, we could say:

print strng[4:8]

which returns 'time'. Like ourfor loop in part 1, the countingstops at 8, but does not returnthe 8th character, which would

be the space after 'time'.

We can find out how longour string is by using the len()function:

print len(strng)

which returns 17. If we want tofind out where in our string theword 'time' is, we could use

pos = strng.find('time')

Now, the variable pos (shortfor position) contains 4, sayingthat 'time' starts at position 4in our string. If we asked thefind function to find a word orsequence that doesn't exist inthe string like this:

pos = strng.find('apples')

the returned value in pos wouldbe -1.

We can also get eachseparate word in the string byusing the split command. Wewill split (or break) the string ateach space character by using:

print strng.split(' ')

which returns a list containing

['The', 'time', 'has', 'come'].This is very powerful stuff.There are many other built-instring functions, which we'll beusing later on.

There is one other thing thatI will introduce before we get toour next programmingexample. When we want toprint something that includesliteral text as well as variabletext, we can use what's calledVariable Substitution. To do thisis rather simple. If we want tosubstitute a string, we use '%s'and then tell Python what tosubstitute. For example, toprint a month from our listabove, we can use:

print 'Month = %s' %month[0]

This would print 'Month =Jan'. If we want to substitute aninteger, we use '%d'. Look atthe example below:

Months =['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec']DaysInMonth =[31,28,31,30,31,30,31,31,30,3

1,30,31]for cntr in range(0,12):

print '%s has %ddays.' %(Months[cntr],DaysInMonth[cntr])

The result from this code is:

Jan has 31 days.Feb has 28 days.Mar has 31 days.Apr has 30 days.May has 31 days.Jun has 30 days.Jul has 31 days.Aug has 31 days.Sep has 30 days.Oct has 31 days.Nov has 30 days.Dec has 31 days.

Something important tounderstand here is the use ofsingle quotes and doublequotes. If you assign a variableto a string like this:

st = 'The time has come'

or like this:

st = “The time has come”

the result is the same.However, if you need to includea single quote in the string likethis:

Page 9: PROGRAM IN PYTHON - Full Circledl.fullcirclemagazine.org/issuePY01_en.pdf · PROGRAMMING SERIES SPECIAL EDITION PROGRAM IN PYTHON Volume One Full Circle Magazine is neither affiliated,

full circle magazine #28 9 contents ^

PROGRAM IN PYTHON - PART 2st = 'He said he's on hisway'

you will get a syntax error. Youneed to assign it like this:

st = “He said he's on hisway”

Think of it this way. To definea string, you must enclose it insome kind of quotes ‒ one atthe beginning, and one at theend ‒ and they must match. Ifyou need to mix quotes, usethe outer quotes to be the onesthat aren't in the string asabove. You might ask, what if Ineed to define a string like“She said “Don't Worry””? Inthis case, you could define itthis way:

st = 'She said “Don\'tWorry”'

Notice the backslash beforethe single quote in 'Don't'. Thisis called an escape character,and tells Python to print the (inthis case) single-quote ‒without considering it as astring delimiter. Other escapecharacter sequences (to showjust a few) would be '\n' fornew line, and '\t' for tab. We'lldeal with these in later sample

code.

We need to learn a few morethings to be able to do our nextexample. First is the differencebetween assignment andequate. We've used theassignment many times in oursamples. When we want toassign a value to a variable, weuse the assignment operator orthe '=' (equal sign):

variable = value

However, when we want toevaluate a variable to a value,we must use a comparisonoperator. Let's say we want tocheck to see if a variable isequal to a specific value. Wewould use the '==' (two equalsigns):

variable == value

So, if we have a variablenamed loop and we want tosee if it is equal to, say, 12, wewould use:

if loop == 12:

Don't worry about the if andthe colon shown in theexample above yet. Justremember we have to use thedouble-equal sign to doevaluation.

The next thing we need todiscuss is comments.Comments are important formany things. Not only do theygive you or someone else anidea of what you are trying todo, but when you come back toyour code, say 6 months fromnow, you can be reminded ofwhat you were trying to do.When you start writing manyprograms, this will becomeimportant. Comments alsoallow you to make Pythonignore certain lines of code. Tocomment a line you use the '#'sign. For example:

# This is a comment

You can put commentsanywhere on a code line, butremember when you do,Python will ignore anythingafter the '#'.

Now we will return to the "if"statement we showed brieflyabove. When we want to makea decision based on values ofthings, we can use the ifstatement:

if loop == 12:

This will check the variable'loop', and, if the value is 12,then we do whatever is in theindented block below. Manytimes this will be sufficient,but, what if we want to say If avariable is something, then dothis, otherwise do that. Inpseudo code you could say:

if x == y thendo something

elsedo something else

and in Python we would say:

if x == y:do something

else:do something elsemore things to do

The main things toremember here are:

1. End the if or else statements

Page 10: PROGRAM IN PYTHON - Full Circledl.fullcirclemagazine.org/issuePY01_en.pdf · PROGRAMMING SERIES SPECIAL EDITION PROGRAM IN PYTHON Volume One Full Circle Magazine is neither affiliated,

full circle magazine #28 10 contents ^

PROGRAM IN PYTHON - PART 2with a colon.

2. INDENT your code lines.

Assuming you have morethan one thing to check, youcan use the if/elif/else format.For example:

x = 5if x == 1:

print 'X is 1'elif x < 6:

print 'X is less than6'elif x < 10:

print 'X is less than10'else:

print 'X is 10 orgreater'

Notice that we are using the'<' operator to see if x is LESSTHAN certain values - in thiscase 6 or 10. Other commoncomparison operators would begreater than '>', less than orequal to '<=', greater than orequal to '>=', and not equal'!='.

Finally, we'll look at a simpleexample of the whilestatement. The whilestatement allows you to create

a loop doing a series ofsteps over and over,until a specificthreshold has beenreached. A simpleexample would beassigning a variable“loop” to 1. Then whilethe loop variable is lessthan or equal to 10, print thevalue of loop, add one to it andcontinue, until, when loop isgreater than 10, quit:

loop = 1while loop <= 10:

print looploop = loop + 1

run in a terminal wouldproduce the following output:

12345678910

This is exactly what wewanted to see. Fig.1 (aboveright) is a similar example thatis a bit more complicated, butstill simple.

In this example, we arecombining the if statement,while loop, raw_inputstatement, newline escapesequence, assignmentoperator, and comparisonoperator ‒ all in one 8 lineprogram.

Running this example wouldproduce:

Enter something or 'quit' toend=> FROG

You typed FROGEnter something or 'quit' toend=> bird

You typed birdEnter something or 'quit' toend=> 42

You typed 42Enter something or 'quit' toend=> QUIT

You typed QUITEnter something or 'quit' toend

=> quitquitting

Notice that when we typed'QUIT', the program did notstop. That's because we areevaluating the value of theresponse variable to 'quit'(response == 'quit'). 'QUIT'does NOT equal 'quit'.

One more quick examplebefore we leave for this month.Let's say you want to check tosee if a user is allowed toaccess your program. Whilethis example is not the bestway to do this task, it's a goodway to show some things thatwe've already learned.Basically, we will ask the userfor their name and a password,compare them with informationthat we coded inside theprogram, and then make adecision based on what wefind. We will use two lists ‒ oneto hold the allowed users and

loop = 1while loop == 1:

response = raw_input("Enter something or 'quit' to end => ")if response == 'quit':

print 'quitting'loop = 0

else:print 'You typed %s' % response

Page 11: PROGRAM IN PYTHON - Full Circledl.fullcirclemagazine.org/issuePY01_en.pdf · PROGRAMMING SERIES SPECIAL EDITION PROGRAM IN PYTHON Volume One Full Circle Magazine is neither affiliated,

full circle magazine #28 11 contents ^

is owner of, a

consulting company in Aurora,Colorado, and has beenprogramming since 1972. Heenjoys cooking, hiking, music,and spending time with hisfamily.

PROGRAM IN PYTHON - PART 2one to hold the passwords.Then we'll use raw_input to getthe information from the user,and finally the if/elif/elsestatements to check anddecide if the user is allowed.Remember, this is not the bestway to do this. We'll examineother ways in later articles.Our code is shown in the boxto the right.

Save this as'password_test.py' and run itwith various inputs.

The only thing that wehaven't discussed yet is in thelist checking routine startingwith 'if usrname in users:'.What we are doing is checkingto see if the user's name thatwas entered is in the list. If itis, we get the position of theuser's name in the list users.Then we useusers.index(usrname) to getthe position in the users list sowe can pull the password,stored at the same position inthe passwords list. Forexample, John is at position 1in the users list. His password,'dog' is at position 1 of thepasswords list. That way wecan match the two. Should be

pretty easy to understand atthis point.

#-----------------------------------------------#password_test.py# example of if/else, lists, assignments,raw_input,# comments and evaluations#-----------------------------------------------# Assign the users and passwordsusers = ['Fred','John','Steve','Ann','Mary']passwords = ['access','dog','12345','kids','qwerty']#-----------------------------------------------# Get username and passwordusrname = raw_input('Enter your username => ')pwd = raw_input('Enter your password => ')#-----------------------------------------------# Check to see if user is in the listif usrname in users:

position = users.index(usrname) #Get the position in the list of the usersif pwd == passwords[position]: #Find the password at position

print 'Hi there, %s. Access granted.' % usrnameelse:

print 'Password incorrect. Access denied.'else:

print "Sorry...I don't recognize you. Access denied."

Page 12: PROGRAM IN PYTHON - Full Circledl.fullcirclemagazine.org/issuePY01_en.pdf · PROGRAMMING SERIES SPECIAL EDITION PROGRAM IN PYTHON Volume One Full Circle Magazine is neither affiliated,

full circle magazine #29 7 contents ^

HOW-TO Program In Python - Part 3

FCM#27-28 - Python Parts 1-2

GraphicsDev Internet M/media System

HDDCD/DVD USB Drive Laptop Wireless

In the last article, welearned about lists, literalsubstitution, comments,equate versus assignment,

if statements and whilestatements. I promised you thatin this part we would learnabout modules and functions.So let's get started.

ModulesModules are a way to extend

your Python programming. Youcan create your own, or use

those that come with Python,or use modules that othershave created. Python itselfcomes with hundreds ofvarious modules that makeyour programming easier. A listof the global modules thatcome with Python can be foundathttp://docs.python.org/modindex.html. Some modules areoperating system specific, butmost are totally cross platform(can be used the same way inLinux, Mac and MicrosoftWindows). To be able to use anexternal module, you mustimport it into your program.One of the modules that comeswith Python is called 'random'.This module allows you togenerate pseudo-randomnumbers. We'll use the moduleshown above right in our firstexample.

Let's examine each line ofcode. The first four lines arecomments. We discussed themin the last article. Line five tellsPython to use the randommodule. We have to explicitly

tell Python todo this.

Line sevensets up a 'for'loop to print 14randomnumbers. Lineeight uses therandint() function to print arandom integer between 1 and10. Notice we must tell Pythonwhat module the functioncomes from. We do this bysaying (in this case)random.randint. Why evencreate modules? Well, if everypossible function were includeddirectly into Python, not onlywould Python becomeabsolutely huge and slow, butbug fixing would be anightmare. By using modules,we can segment the code intogroups that are specific to acertain need. If, for example,you have no need to usedatabase functionality, youdon't need to know that thereis a module for SQLite.However, when you need it, it'salready there. (In fact, we'll be

using database modules lateron in this series.)

Once you really get startedin Python programming, youwill probably make your ownmodules so you can use thecode you've already writtenover and over again, withouthaving to re-type it. If you needto change something in thatgroup of code, you can, withvery little risk of breaking thecode in your main program.There are limits to this and wewill delve into this later on.Now, when we used the 'importrandom' statement earlier, wewere telling Python to give usaccess to every function withinthe random module. If,however, we only needed touse the randint() function, we

#=======================================# random_example.py# Module example using the random module#=======================================import random# print 14 random integersfor cntr in range(1,15):

print random.randint(1,10)

Page 13: PROGRAM IN PYTHON - Full Circledl.fullcirclemagazine.org/issuePY01_en.pdf · PROGRAMMING SERIES SPECIAL EDITION PROGRAM IN PYTHON Volume One Full Circle Magazine is neither affiliated,

full circle magazine #29 8 contents ^

PROGRAM IN PYTHON - PART 3can re-work the importstatement like this:

from random import randint

Now when we call ourfunction, we don't have to usethe 'random.' identifier. So, ourcode changes to

from random import randint# print 14 random integersfor cntr in range(1,15):

print randint(1,10)

FunctionsWhen we imported the

random module, we used therandint() function. A function isa block of code that isdesigned to be called, usuallymore than once, which makesit easier to maintain, and tokeep us from typing the samecode over and over and over.As a very general and grossstatement, any time you haveto write the same code morethan once or twice, that code isa good candidate for afunction. While the followingtwo examples are silly, theymake good statements aboutusing functions. Let's say wewanted to take two numbers,

add them, thenmultiply them, andthen subtract them,displaying thenumbers and resultseach time. To makematters worse, wehave to do that threetimes with three setsof numbers. Our sillyexample would thenlook like the textshown right.

Not only is this a lot oftyping, it lends itself to errors,either by typing or having tochange something later on.Instead, we are going to createa function called 'DoTwo' thattakes the two numbers anddoes the math, printing theoutput each time. We start byusing the 'def' key word (whichsays that we are going todefinethefunction).After'def'weaddthenamewe

select for the function, andthen a list of parameters (ifany) in parentheses. This line isthen closed by a colon (:). Thecode in the function isindented. Our improved sillyexample (#2) is shown below.

As you can see, there's a lotless typing involved — 8 linesinstead of 12 lines. If we needto change something in our

function, we can do it withoutcausing too many issues to ourmain program. We call ourfunction, in this case, by usingthe function name and puttingthe parameters after.

Here is another example ofa function. Consider thefollowing requirements.

We want to create a

#silly exampleprint 'Adding the two numbers %d and %d = %d ' % (1,2,1+2)print 'Multiplying the two numbers %d and %d = %d ' % (1,2,1*2)print 'Subtracting the two numbers %d and %d = %d ' % (1,2,1-2)print '\n'print 'Adding the two numbers %d and %d = %d ' % (1,4,1+4)print 'Multiplying the two numbers %d and %d = %d ' % (1,4,1*4)print 'Subtracting the two numbers %d and %d = %d ' % (1,4,1-4)print '\n'print 'Adding the two numbers %d and %d = %d ' % (10,5,10+5)print 'Multiplying the two numbers %d and %d = %d ' % (10,5,10*5)print 'Subtracting the two numbers %d and %d = %d ' % (10,5,10-5)print '\n'

#silly example 2...still silly, but betterdef DoTwo(num1,num2):

print 'Adding the two numbers %d and %d = %d ' % (num1,num2,num1+num2)print 'Multiplying the two numbers %d and %d = %d ' % (num1,num2,num1*num2)print 'Subtracting the two numbers %d and %d = %d ' % (num1,num2,num1-num2)print '\n'

DoTwo(1,2)DoTwo(1,4)DoTwo(10,5)

Page 14: PROGRAM IN PYTHON - Full Circledl.fullcirclemagazine.org/issuePY01_en.pdf · PROGRAMMING SERIES SPECIAL EDITION PROGRAM IN PYTHON Volume One Full Circle Magazine is neither affiliated,

full circle magazine #29 9 contents ^

PROGRAM IN PYTHON - PART 3program that will print out alist of purchased items in apretty format. It must looksomething like the text below.

The cost of each item andfor the total of all items will beformatted as dollars and cents.The width of the print out mustbe able to be variable. Thevalues on the left and rightmust be variable as well. Wewill use 3 functions to do thistask. One prints the top andbottom line, one prints theitem detail lines including thetotal line and one prints theseparator line. Luckily, thereare a number of things thatPython has that will make thisvery simple. If you recall, weprinted a string multiplied by 4,and it returned four copies ofthe same string. Well we canuse that to our benefit. To printour top or bottom line we cantake the desired width,subtract two for the two +

characters and use “ '=' *(width-2)”. To make thingseven easier, we will usevariable substitution to put allthese items on one line. So ourstring to print would be codedas 's ('+',('=' * width-2)),'+').Now we could have the routineprint this directly, but we willuse the return keyword to sendthe generated string back toour calling line. We'll call ourfunction 'TopOrBottom' and thecode for this function looks likethis.

def TopOrBottom(width):# width is total width

of returned linereturn '%s%s%s' %

('+',('=' * (width-2)),'+')

We could leave out thecomment, but it's nice to beable to tell at a glance whatthe parameter 'width' is. To callit, we would say 'printTopOrBottom(40)' or whateverwidth we wish the line to be.

Now we have onefunction that takescare of two of thelines. We can make anew function to takecare of the separatorline using the samekind of code...OR we

could modify the function wejust made to include aparameter for the character touse in the middle of the pluses.Let's do that. We can still call itTopOrBottom.

defTopOrBottom(character,width):

# width is total widthof returned line

# character is thecharacter to be placedbetween the '+' characters

return '%s%s%s' %('+',(character * (width-2)),'+')

Now, you can see wherecomments come in handy.Remember, we are returningthe generated string, so wehave to have something toreceive it back when we makethe call to it. Instead ofassigning it to another string,we'll just print it. Here's thecalling line.

print TopOrBottom('=',40)

So now, not only have wetaken care of three of the lines,we've reduced the number ofroutines that we need from 3down to 2. So we only have thecenter part of the print out todeal with.

Let's call the new function'Fmt'. We'll pass it 4 parametervalues as follows:

– the value to print on theleft

– the width of this“column”

– the value to print on theright (which should be afloating value)

– the width of this“column”

The first task is to formatthe information for the rightside. Since we want to formatthe value to represent dollarsand cents, we can use a specialfunction of variablesubstitution that says, print thevalue as a floating pointnumber with n number ofplaces to the right of thedecimal point. The commandwould be '%2.f'. We will assignthis to a variable called 'part2'.So our code line would be'part2 = '%.2f' % val2'. We alsocan use a set of functionsthat's built into Python stringscalled ljust and rjust. Ljust willleft justify the string, paddingthe right side with whatevercharacter you want. Rjust does

'+===============================+''| Item 1 X.XX |''| Item 2 X.XX |''|-------------------------------|''| Total X.XX |''+===============================+'

Page 15: PROGRAM IN PYTHON - Full Circledl.fullcirclemagazine.org/issuePY01_en.pdf · PROGRAMMING SERIES SPECIAL EDITION PROGRAM IN PYTHON Volume One Full Circle Magazine is neither affiliated,

full circle magazine #29 10 contents ^

PROGRAM IN PYTHON - PART 3the same thing, except thepadding goes on the left side.Now for the neat bit. Usingsubstitutions we throwtogether a big string and returnthat to the calling code. Here isour next line.

return 'ss' % ('|',val1.ljust(leftbit-2,''),part2.rjust(rightbit-2,''),' |')

While this looks ratherdaunting at first, let's dissect itand see just how easy it is:

- We will send backour created string to thecalling code.

- We are going to stick in4 values in the string. Each%s is a place holder.

- Starts the variable list- Print these literals

-Take the variable val1 that wewere passed, left justify itwith spaces for (leftbit-2)characters. We subtract 2 toallow the '| ' on the left side.

-Right justify the formattedstring of the price rightbit-2spaces. ' |' - finish the string.

That's all there is to it.

While we should really do someerror checking, you can usethat as something to play withon your own. So...our Fmtfunction is really only two linesof code outside of thedefinition line and anycomments. We can call it likethis.

print Fmt('Item1',30,item1,10)

Again, we could assign thereturn value to another string,

but we can justprint it. Noticethat we aresending 30 forthe width of theleft bit and 10for the width ofthe right. That equals the 40that we sent to ourTopOrBottom routine earlier.So, fire up your editor and typein the code below.

Save the code as'pprint1.py' and run it. Your

output should look somethinglike the text shown above right.

While this is a very simpleexample, it should give you agood idea of why and how touse functions. Now, let'sextend this out a bit and learn

#pprint1.py#Example of semi-useful functions

def TopOrBottom(character,width):# width is total width of returned linereturn '%s%s%s' % ('+',(character * (width-2)),'+')

def Fmt(val1,leftbit,val2,rightbit):# prints two values padded with spaces# val1 is thing to print on left, val2 is thing to print on right# leftbit is width of left portion, rightbit is width of right portionpart2 = '%.2f' % val2return '%s%s%s%s' % ('| ',val1.ljust(leftbit-2,' '),part2.rjust(rightbit-2,' '),' |')

# Define the prices of each itemitem1 = 3.00item2 = 15.00# Now print everything out...print TopOrBottom('=',40)print Fmt('Item 1',30,item1,10)print Fmt('Item 2',30,item2,10)print TopOrBottom('-',40)print Fmt('Total',30,item1+item2,10)print TopOrBottom('=',40)

+======================================+| Item 1 3.00 || Item 2 15.00 |+--------------------------------------+| Total 18.00 |+======================================+

Page 16: PROGRAM IN PYTHON - Full Circledl.fullcirclemagazine.org/issuePY01_en.pdf · PROGRAMMING SERIES SPECIAL EDITION PROGRAM IN PYTHON Volume One Full Circle Magazine is neither affiliated,

full circle magazine #29 11 contents ^

is owner of, a

consulting company in Aurora,Colorado, and has beenprogramming since 1972. Heenjoys cooking, hiking, music,and spending time with hisfamily.

PROGRAM IN PYTHON - PART 3more about lists. Rememberback in part 2 when we firstdiscussed lists? Well one thingthat I didn't tell you is that alist can contain just aboutanything, including lists. Let'sdefine a new list in ourprogram called itms and fill itlike this:

itms =[['Soda',1.45],['Candy',.75],['Bread',1.95],['Milk',2.59]]

If we were to access this asa normal list we would useprint itms[0]. However, whatwe would get back is['Soda',1.45], which is notreally what we were looking forunder normal circumstances.We want to access each item inthat first list. So we would use'print itms[0][0]' to get 'Soda'and [0][1] to get the cost or1.45. So, now we have 4 itemsthat have been purchased andwe want to use thatinformation in our pretty printroutine. The only thing we haveto change is at the bottom ofthe program. Save the lastprogram as 'pprint2.py', thencomment out the two itemxdefinitions and insert the listwe had above. It should look

like this now.

#item1 = 3.00#item2 = 15.00itms =[['Soda',1.45],['Candy',.75],['Bread',1.95],['Milk',2.59]]

Next, remove allthe lines that callFmt(). Next add thefollowing lines (with#NEW LINE at the end) tomake your code look like thetext shown right.

I set up a counter variablefor loop that cycles through thelist for each item there. Noticethat I've also added a variablecalled total. We set the total to0 before we go into our forloop. Then as we print eachitem sold, we add the cost toour total. Finally, we print thetotal out right after theseparator line. Save yourprogram andrun it. Youshould seesomething likethe text shownbelow.

If youwanted to get

wild and crazy, you could add aline for tax as well. Handle itclose to the same way we didthe total line, but use (total *.086) as the cost.

printFmt('Tax:',30,total*.086,10)

If you would like to, you canadd more items to the list andsee how it works.

That's it for this time. Nexttime we'll concentrate onclasses.

itms = [['Soda',1.45],['Candy',.75],['Bread',1.95],['Milk',2.59]]

print TopOrBottom('=',40)

total = 0 #NEW LINEfor cntr in range(0,4): #NEW LINE

print Fmt(itms[cntr][0],30,itms[cntr][1],10) #NEW LINEtotal += itms[cntr][1] #NEW LINE

print TopOrBottom('-',40)print Fmt('Total',30,total,10) #CHANGED LINEprint TopOrBottom('=',40)

+======================================+| Soda 1.45 || Candy 0.75 || Bread 1.95 || Milk 2.59 |+--------------------------------------+| Total 6.74 |+======================================+

Page 17: PROGRAM IN PYTHON - Full Circledl.fullcirclemagazine.org/issuePY01_en.pdf · PROGRAMMING SERIES SPECIAL EDITION PROGRAM IN PYTHON Volume One Full Circle Magazine is neither affiliated,

full circle magazine #30 7 contents ^

HOW-TO Program In Python - Part 4

FCM#27-29 - Python Parts 1-3

GraphicsDev Internet M/media System

HDDCD/DVD USB Drive Laptop Wireless

Ipromised last time that wewould discuss classes. So,that's what we'llconcentrate on. What are

classes and what good are they?

A class is a way ofconstructing objects. An objectis simply a way of handlingattributes and behaviors as agroup. I know this soundsconfusing, but I'll break it downfor you. Think of it this way. Anobject is a way to modelsomething in the real world. A

class is a method we use toimplement this. For example,we have three dogs at home. ABeagle, a Lab and a GermanShepherd/Blue Heeler mix. Allthree are dogs, but are alldifferent. There are commonattributes among the three ofthem, but each dog hasseparate attributes as well. Forexample, the Beagle is short,chubby, brown, and grumpy.The Lab is medium-sized,black, and very laid back. TheShepherd/Heeler mix is tall,skinny, black, and more than abit crazy. Right away, someattributes are obvious.Short/medium-sized/tall are allattributes of height. Grumpy,laid back, and crazy are all

attributes of mood. On thebehavior side of things, we canconsider eating, sleeping,playing, and other actions.

All three are of the class'Dog'. Going back to theattributes that we used todescribe each above, we havethings such as Dog.Name,Dog.Height, Dog.Build (skinny,chubby, etc.), and Dog.Color.We also have behaviors suchas Dog.Bark, Dog.Eat,Dog.Sleep, and so on.

As I said before, each of thedogs is a different breed. Eachbreed would be a sub-class ofthe class Dog. In a diagram, itwould look like this.

/--BeagleDog ---|-- Lab

\--Shepherd/Heeler

Each sub-class inherits all ofthe attributes of the Dog class.Therefore, if we create aninstance of Beagle, it gets all ofthe attributes from its parentclass, Dog.

Beagle = Dog()Beagle.Name = 'Archie'Beagle.Height = 'Short'Beagle.Build = 'Chubby'Beagle.Color = 'Brown'

Starting to make sense? So,let's create our gross Dog class(shown above). We'll start withthe keyword "class" and thename of our class.

class Dog():def __init__(self,dogname,dogcolor,dogheight,dogbuild,dogmood,dogage):

#here we setup the attributes of our dogself.name = dognameself.color = dogcolorself.height = dogheightself.build = dogbuildself.mood = dogmoodself.age = dogageself.Hungry = Falseself.Tired = False

Page 18: PROGRAM IN PYTHON - Full Circledl.fullcirclemagazine.org/issuePY01_en.pdf · PROGRAMMING SERIES SPECIAL EDITION PROGRAM IN PYTHON Volume One Full Circle Magazine is neither affiliated,

full circle magazine #30 8 contents ^

PROGRAM IN PYTHON - PART 4Before we go any further in

our code, notice the functionthat we have defined here. Thefunction __init__ (twounderscores + 'init' + twounderscores) is an initializationfunction that works with anyclass. As soon as we call ourclass in code, this routine isrun. In this case, we have setup a number of parameters toset some basic informationabout our class: we have aname, color, height, build,mood, age, and a couple ofvariables Hungry and Tired.We'll revisit these in a little bit.Now let's add some more code.

Beagle =Dog('Archie','Brown','Short','Chubby','Grumpy',12)print Beagle.nameprint Beagle.colorprint Beagle.moodprint Beagle.Hungry

This is UNINDENTED codethat resides outside of ourclass, the code that uses ourclass. The first line creates aninstance of our dog class calledBeagle. This is calledinstantiation. When we did this,we also passed certaininformation to the instance ofthe class, such as the Beagle's

name, color, and so on. Thenext four lines simply querythe Beagle object and get backinformation in return. Time formore code. Add the codeshown in the top right box intothe class after the __init__function.

Now we can call it withBeagle.Eat() or Beagle.Sleep().Let's add one more method.We'll call it Bark. Its code isshown right.

This one I've made moreflexible. Depending on themood of the dog, the bark willchange. Shown on the nextpage is the full class code sofar.

So, when we run this we'llget

My name is ArchieMy color is BrownMy mood is GrumpyI am hungry = FalseSniff Sniff...Not HungryYum Yum...Num NumGRRRRR...Woof Woof

Now, that takes care of thegrumpy old Beagle. However, Isaid earlier that I have 3 dogs.Because we coded the class

carefully, all we have to do iscreate two more instances ofour dog class.

Lab =Dog('Nina','Black','Medium','Heavy','Laid Back',7)Heeler =Dog('Bear','Black','Tall','Skinny','Crazy',9)print 'My Name is %s' %Lab.nameprint 'My color is %s' %Lab.colorprint 'My Mood is %s' %Lab.moodprint 'I am hungry = %s' %Lab.HungryLab.Bark()Heeler.Bark()

Notice that I created theinstances of both of the dogsbefore I did the printstatements. That's not aproblem, since I “defined” theinstance before I called any ofthe methods. Here is the fulloutput of our dog classprogram.

My name is ArchieMy color is BrownMy mood is GrumpyI am hungry = FalseSniff Sniff...Not HungryYum Yum...Num NumGRRRRR...Woof WoofMy Name is Nina

def Eat(self):if self.Hungry:

print 'Yum Yum...Num Num'self.Hungry = False

else:print 'Sniff Sniff...Not Hungry'

def Sleep(self):print 'ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ'self.Tired = False

def Bark(self):if self.mood == 'Grumpy':

print 'GRRRRR...Woof Woof'elif self.mood == 'Laid Back':

print 'Yawn...ok...Woof'elif self.mood == 'Crazy':

print 'Bark Bark Bark Bark Bark Bark Bark'else:

print 'Woof Woof'

Page 19: PROGRAM IN PYTHON - Full Circledl.fullcirclemagazine.org/issuePY01_en.pdf · PROGRAMMING SERIES SPECIAL EDITION PROGRAM IN PYTHON Volume One Full Circle Magazine is neither affiliated,

full circle magazine #30 9 contents ^

PROGRAM IN PYTHON - PART 4

is owner of, a

consulting company in Aurora,Colorado, and has beenprogramming since 1972. Heenjoys cooking, hiking, music,and spending time with hisfamily.

My color is BlackMy Mood is Laid BackI am hungry = FalseYawn...ok...WoofBark Bark Bark Bark BarkBark Bark

Now that you have thebasics, your homework will beto expand our dog class toallow for more methods, suchas maybe Play orEncounterStrangeDog orsomething like this.

Next time, we will startdiscussing GUI or GraphicalUser Interface programming.We will be using

for this.

class Dog():def __init__(self,dogname,dogcolor,dogheight,dogbuild,dogmood,dogage):

#here we setup the attributes of our dogself.name = dognameself.color = dogcolorself.height = dogheightself.build = dogbuildself.mood = dogmoodself.age = dogageself.Hungry = Falseself.Tired = False

def Eat(self):if self.Hungry:

print 'Yum Yum...Num Num'self.Hungry = False

else:print 'Sniff Sniff...Not Hungry'

def Sleep(self):print 'ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ'self.Tired = False

def Bark(self):if self.mood == 'Grumpy':

print 'GRRRRR...Woof Woof'elif self.mood == 'Laid Back':

print 'Yawn...ok...Woof'elif self.mood == 'Crazy':

print 'Bark Bark Bark Bark Bark Bark Bark'else:

print 'Woof Woof'

Beagle = Dog('Archie','Brown','Short','Chubby','Grumpy',12)print 'My name is %s' % Beagle.nameprint 'My color is %s' % Beagle.colorprint 'My mood is %s' % Beagle.moodprint 'I am hungry = %s' % Beagle.HungryBeagle.Eat()Beagle.Hungry = TrueBeagle.Eat()Beagle.Bark()

Page 20: PROGRAM IN PYTHON - Full Circledl.fullcirclemagazine.org/issuePY01_en.pdf · PROGRAMMING SERIES SPECIAL EDITION PROGRAM IN PYTHON Volume One Full Circle Magazine is neither affiliated,

full circle magazine #31 contents ^

HOW-TO Program In Python - Part 5

FCM#27-30 - Python Parts 1-4

GraphicsDev Internet M/media System

HDDCD/DVD USB Drive Laptop Wireless

If you are like me, you willHATE the first part of thisinstallation. I HATE it whenan author tells me that I

have to double read every wordin their book/chapter/article,because I just KNOW it will be asnore - even when I know it'sfor my own good, and I will endup doing it anyway.

Consider yourself warned.PLEASE read the followingboring stuff carefully. We'll getto the fun stuff soon, but we

need to get some ground workcovered before we can reallytalk about trying to program.

FIRST you need to installBoa Constructor and wxPython.Use Synaptic and select bothwxPython and Boa Constructor.Once installed, you should findBoa underApplications|Programming\BoaConstructor. Go ahead andstart it up. It will make things abit easier. Once the applicationstarts, you will see threedifferent windows (or frames):one across the top, and twoacross the bottom. You mighthave to resize and move thema bit, but get things to a pointwhere it looks something likethis:

The top frame is called thetool frame. The bottom-leftframe is the inspector frame,and the bottom-right frame isthe editor frame. On the toolframe, you have various tabs(New, Containers/Layout, etc.)that will allow you to start newprojects, add frames toexisting projects, and addvarious controls to the framesfor your application. Theinspector frame will becomevery important as we start toadd controls to our application.The editor frame allows us toedit our code, save ourprojects, and more. Moving ourattention back to the toolframe, let's take a look at eachtab - starting with the “New”tab. While there are manyoptions available here, we willdiscuss only two of them. Theyare the 5th and 6th buttonsfrom the left: wx.App andwx.Frame. Wx.App allows us tocreate a complete applicationbeginning with two auto-generated files. One is a framefile and the other is anapplication file. This is the

method I prefer to use. Thewx.Frame is used to add moreframes to our applicationand/or create a standalone appfrom a single source file. We'lldiscuss this later.

Now look at theContainers/Layout tab. Manygoodies here. The ones you'lluse most are the wx.Panel(first on the left) and the sizers(2,3,4,5 and 6 from the right).Under Basic Controls, you'llfind static text controls(labels), text boxes, checkboxes, radio buttons, andmore. Under Buttons, you'llfind various forms of buttons.List Controls has data grids andother list boxes. Let's jump toUtilities where you'll find timersand menu items.

Here are a few things toremember as we are gettingready for our first app. Thereare a few bugs in the Linuxversion. One is that SOMEcontrols won't allow you tomove them in the designer.Use the <Ctrl>+Arrow keys to

Page 21: PROGRAM IN PYTHON - Full Circledl.fullcirclemagazine.org/issuePY01_en.pdf · PROGRAMMING SERIES SPECIAL EDITION PROGRAM IN PYTHON Volume One Full Circle Magazine is neither affiliated,

full circle magazine #31 contents ^

PROGRAM IN PYTHON - PART 5move or tweak the position ofyour controls. Another oneyou'll find when you try thetutorials that come with BoaConstructor - when placing apanel control, it's hard to see.Look for the little boxes (I'llshow you this soon). You canalso use the Objs tab on theInspector frame and select itthat way.

Okay, here we go. Under the'New' tab of the tool frame,select wx.App (5th button fromthe left). This will create twonew tabs in the editor frame:one named “*(App1)*”, theother named “*(Frame1)*”.Believe it or not, the VERY firstthing we want to do is save ourtwo new files, starting with theFrame1 file. The save button isthe 5th button from the left inthe Editor Frame. A “Save As”frame will pop up asking youwhere you want to save the fileand what you want to call it.Create a folder in your homefolder called GuiTests, and savethe file as “Frame1.py”. Noticethat the “*(Frame1)*” tab nowshows as “Frame1”. (The “*(“says that the file needs to besaved.) Now do the same thingwith the App1 tab.

Now let's examine a few ofthe buttons on the Editor Toolbar. The important ones fornow are the Save (5th from theleft) and Run (Yellow arrow, 7thfrom the left). If you are in aframe tab (Frame1 forexample) there will be someextra buttons you need toknow about. For now it's theDesigner button:

It is an important one. Itallows us to design our GUIframe - which is what we'll donow. When you click on it youwill be presented with a blankframe.

This is a blank canvas foryou to put whatever controlsyou need to (within reason).The first thing we want to do isplace a wx.panel control.Almost everything I have read

says not to put controls (otherthan a wx.panel) directly on aframe. So, click on theContainers/Layout tab in theTool Frame, then click on thewx.Panel button. Next, moveover to the new frame that youare working on and clicksomewhere on the inside of theframe. You'll know it worked ifyou see something like this:

Remember when I warnedyou about the bugs? Well, thisis one of them. Don't worry.See the 8 little black squares?That's the limits of the panel. Ifyou wanted, you could clickand drag one of them to resizethe panel, but for this projectwhat we want is to make thepanel cover the entire frame.Simply resize the FRAME just alittle bit at this point. Now wehave a panel to put our othercontrols on. Move the frameyou are working on until you

can see the tool box for theEditor frame. Two new buttonshave appeared: a check and an“X”. The “X” will cause thechanges you made to bethrown away.

The Check button:

is called the “Post” button. Thiswill cause your changes to bewritten into our frame file. Youstill have to save the frame file,but this will get the new thingsinto the file. So, click on thePost button. There's also a postbutton on the Inspector frame,but we'll deal with that later.Now save your file.

Go back into the Designmode. Click the 'Buttons' tabon the Tool frame and thenclick the first button on the left,the wx.Button. Then add itsomewhere close to the middleof your frame. You'll havesomething that looks close tothis:

Page 22: PROGRAM IN PYTHON - Full Circledl.fullcirclemagazine.org/issuePY01_en.pdf · PROGRAMMING SERIES SPECIAL EDITION PROGRAM IN PYTHON Volume One Full Circle Magazine is neither affiliated,

full circle magazine #31 contents ^

PROGRAM IN PYTHON - PART 5Notice that there are 8 small

squares around it just like thepanel. These are resizehandles. It also shows us whatcontrol is currently selected. Inorder to move this closer to thecenter of the frame, hold downthe Control key (Ctrl) and whilethat's being pressed, use thearrow keys to move it whereyou want it. Now, let's look atthe Inspector frame. There arefour tabs. Click on the 'Constr'tab. Here we can change thelabel, name, position, size andstyle. For now, let's change thename to 'btnShowDialog' andthe Label property to 'Click Me'.

Now, let's skip over all therest of that tab and go to theObjs tab. This tab shows all thecontrols you have and theirparent/child relationships. Asyou can see, the button is achild of panel1, which is a childof Frame1.

Post (check button) andsave your changes. Go back tothe designer once again, andnotice that (assuming you stillhave the 'Objs' tab in theinspector frame selected),Frame1 is now selected. This isgood because it's what wewant. Go back to the 'Constr'tab, and change the title from'Frame1' to 'Our First GUI'. Postand save one more time. Nowlet's run our app. Click theyellow Run button on the Editorframe.

Click all you want on thebutton, but nothing willhappen. Why? Well, we didn't

tell the button to do anything.For that, we need to set up anevent to happen, or fire, whenthe user clicks our button. Clickon the X in the upper-rightcorner to finish running theframe. Next, go back to thedesigner, select the button andgo into the 'Evts' tab in theinspector frame. Click onButtonEvent and then doubleclick on the wx.EVT_BUTTONtext that shows up, and noticethat in the window below weget a button event called'OnBtnShowDialogButton'. Postand save.

Before we go any further,let's see what we've got in theway of code (page 11).

The first line is a commentthat tells Boa Constructor that

this is a boa file. It's ignored bythe Python compiler, but not byBoa. The next line importswxPython. Now jump down tothe class definition.

At the top, there's the__init_ctrls method. Notice thecomment just under thedefinition line. Don't edit thecode in this section. If you do,you will be sorry. Any placeBELOW that routine should besafe. In this routine, you willfind the definitions of eachcontrol on our frame.

Next, look at the __init__routine. Here you can put anycalls to initializing code. Finally,the OnBtnShowDialogButtonroutine. This is where we willput our code that will do thework when the user clicks thebutton. Notice that there iscurrently an event.Skip() linethere. Simply stated, this saysjust exit when this event fires.

Now, what we are going todo is call a message box to popup with some text. This is acommon thing forprogrammers to do to allow theuser to know about something -an error, or the fact that a

Page 23: PROGRAM IN PYTHON - Full Circledl.fullcirclemagazine.org/issuePY01_en.pdf · PROGRAMMING SERIES SPECIAL EDITION PROGRAM IN PYTHON Volume One Full Circle Magazine is neither affiliated,

full circle magazine #31 contents ^

is owner of, a

consulting company in Aurora,Colorado, and has beenprogramming since 1972. Heenjoys cooking, hiking, music,and spending time with hisfamily.

process has finished. In thiscase, we will be calling thewx.MessageBox built inroutine. The routine is calledwith two parameters. The firstis the text we wish to send inthe message box and thesecond is the title for themessage box. Comment outthe line event.Skip() and put inthe following line.

wx.MessageBox('You Clickedthe button', 'Info')

Save and click the Runbutton (yellow arrow). Youshould see something like this:

And when you click thebutton you should seesomething like this:

Understand herethat this is just aboutthe simplest way tocall the messageboxroutine. You can havemore parameters aswell.

Here's a quickrundown on how tochange the way theicons work on themessage box (morenext time).

- Show a question icon

- Show an alerticon

- Show anerror icon

-Show an info icon

The way to write this wouldbe

wx.MessageBox('You Clickedthe button', 'Info',wx.ICON_INFORMATION)

or whatever icon you wanted

to use that suited the situation.There are also various buttonarrangement assignmentswhich we'll talk about nexttime.

#Boa:Frame:Frame1import wxdef create(parent):

return Frame1(parent)[wxID_FRAME1, wxID_FRAME1BTNSHOWDIALOG, wxID_FRAME1PANEL1,] = [wx.NewId() for _init_ctrls in range(3)]

class Frame1(wx.Frame):def _init_ctrls(self, prnt):

# generated method, don't editwx.Frame.__init__(self, id=wxID_FRAME1, name='', parent=prnt,

pos=wx.Point(543, 330), size=wx.Size(458, 253),style=wx.DEFAULT_FRAME_STYLE, title=u'Our First GUI')

self.SetClientSize(wx.Size(458, 253))self.panel1 = wx.Panel(id=wxID_FRAME1PANEL1, name='panel1', parent=self,

pos=wx.Point(0, 0), size=wx.Size(458, 253),style=wx.TAB_TRAVERSAL)

self.btnShowDialog = wx.Button(id=wxID_FRAME1BTNSHOWDIALOG,label=u'Click Me', name=u'btnShowDialog', parent=self.panel1,pos=wx.Point(185, 99), size=wx.Size(85, 32), style=0)

self.btnShowDialog.Bind(wx.EVT_BUTTON, self.OnBtnShowDialogButton,id=wxID_FRAME1BTNSHOWDIALOG)

def __init__(self, parent):self._init_ctrls(parent)

def OnBtnShowDialogButton(self, event):event.Skip()

PROGRAM IN PYTHON - PART 5

Page 24: PROGRAM IN PYTHON - Full Circledl.fullcirclemagazine.org/issuePY01_en.pdf · PROGRAMMING SERIES SPECIAL EDITION PROGRAM IN PYTHON Volume One Full Circle Magazine is neither affiliated,

full circle magazine #32 contents ^

HOW-TO Program In Python - Part 6

FCM#27-31 - Python Parts 1-5

GraphicsDev Internet M/media System

HDDCD/DVD USB Drive Laptop Wireless

Ihope you've been playingwith Boa Constructor sinceour last meeting. First wewill have a very simple

program that will show oneframe, then allow you to clickon a button that will pop upanother frame. Last time we dida message box. This time wewill do a totally separate frame.This can be helpful when doingan application with multipleframes or windows. So... herewe go...

Start up Boa Constructorand close all tabs in the Editorframe with the exception ofShell and Explorer by using the(Ctrl-W) key combination. Thisensures that we will be startingtotally fresh. Now create a newproject by clicking on thewx.App button (see last time'sarticle if needed).

Before you do anything else,save Frame1 as“FrameMain.py” and then saveApp1 as “Gui2.py”. This isimportant. With the GUI2 tabselected in the Editor frame,move to the Toolbar frame, goback to the New tab, and addanother frame to our project byclicking on wx.Frame (which isright next to the wx.Appbutton). Make sure that theApplication tab shows bothframes under the Modulecolumn. Now go back to thenew frame and save it as“FrameSecond.py”:

Next, open FrameMain inthe designer. Add a wx.Panel tothe frame. Resize it a bit to

make the panel cover theframe. Next we are going tochange some properties - wedidn't do this last time. In theinspector frame, make surethat the Constr tab is selectedand set the title to “MainFrame” and the name to“FrameMain”. We'll discussnaming conventions in a bit.Set the size to 400x340 byclicking on the Size check box.This drops down to showheight and width. Heightshould be 400 and widthshould be 340:

Now click on the Props tab.Click on the Centered propertyand set it to wx.BOTH. Click thepost check-mark and save yourwork. Now run your applicationby clicking on the button withthe yellow arrow. Ourapplication shows up in thecenter of the screen with thetitle of “Main Frame”. Nowclose it by clicking on the “X”in the upper right corner of theapp.

Bring FrameMain back intothe designer. Add twowx.Buttons to the frame, oneabove the other, and close tothe center of the frame. Selectthe top button, name that“btnShowNew”, and set thelabel to “Show the otherframe” in the Constr tab of theInspector frame. Use theShift+Arrow combination toresize the button so that all thetext is visible, and then use theCtrl+Arrow combination tomove it back to the center ofthe frame. Select the bottombutton, name that “btnExit”,and set the label to “Exit”.

Page 25: PROGRAM IN PYTHON - Full Circledl.fullcirclemagazine.org/issuePY01_en.pdf · PROGRAMMING SERIES SPECIAL EDITION PROGRAM IN PYTHON Volume One Full Circle Magazine is neither affiliated,

full circle magazine #32 contents ^

PROGRAM IN PYTHON - PART 6Post, save, and run to see yourchanges. Exit our app and goback to the designer. We aregoing to add button clickevents. Select the top button,and in the inspector frame,select the Evts tab. Click onButtonEvent, then double clickon wx.Evt_BUTTON. Notice youshould have“OnBtnShowNewButton” below.Next, select the btnExit button.Do the same thing, makingsure it shows“OnBtnExitButton”. Post andsave. Next go to the Editorframe and scroll down to thebottom.

Make sure you have the twoevent methods that we justcreated. Here's what the frameshould look like so far:

Now it's time to deal withour other frame. OpenFrameSecond in the designer.

Set the name to“FrameSecond”, and the title to“Second Frame”. Set centeringto wx.BOTH. Add a wx.Button,and center it towards the lowerpart of the frame. Set thename to “btnFSExit”, andchange the title to “Exit”. Setup a button event for it. Nextadd a wx.StaticText control inthe upper portion of the frameclose to the middle. Name it“stHiThere”, set the label to “Hithere...I'm the second form!”,and set the font to Sans, 14point and weight to wxBOLD.Now reset the position to becentered in the form right andleft. You can do this byunchecking the Positionattribute and use the X positionfor right and left, and Y for upand down until you are happy.Post and save:

Now that we have designedour forms, we are going to

create the “glue” that will tieall this together.

In the Editor frame, click onthe GUI2 tab, then, below that,click on the Source tab. Underthe line that says “importFrameMain”, add “importFrameSecond”. Save yourchanges. Next, select the“FrameMain” tab. Under theline that says “import wx”, adda line that says “importFrameSecond”. Next scrolldown, and find the line thatsays “def __init__(self,parent):”. Add a line after the“self._init_ctrls(parent)” linethat says “self.Fs =FrameSecond.FrameSecond(self)”. Now under the “defOnBtnShowNewButton(self,event):” event, comment out“event.Skip()” and add thefollowing two lines:

self.Fs.Show()self.Hide()

Finally, under“OnBtnExitButton” method,comment out “event.Skip()”,and add a line that says“self.Close()”

What does all this do? OK.

The first thing we did was tomake sure that the applicationknew we were going to havetwo forms in our app. That'swhy we imported bothFrameMain and FrameSecondin the GUI2 file. Next weimported a reference forFrameSecond into FrameMainso we can call it later. Weinitialized it in the “_init_”method. And in the“OnBtnShowNewButton” eventwe told it that when the buttonwas clicked, we want to firstshow the second frame, and tohide the main frame. Finally wehave the statement to closethe application when the Exitbutton is clicked.

Now, switch to the code forFrameSecond. The changeshere are relatively small. Underthe “_init_” method, add a linethat says “self.parent =parent” which adds a variableself.parent. Finally, under theclick event for FSExitButton,comment out the“event.Skip()” line, and add thefollowing two lines:

self.parent.Show()self.Hide()

Page 26: PROGRAM IN PYTHON - Full Circledl.fullcirclemagazine.org/issuePY01_en.pdf · PROGRAMMING SERIES SPECIAL EDITION PROGRAM IN PYTHON Volume One Full Circle Magazine is neither affiliated,

full circle magazine #32 contents ^

PROGRAM IN PYTHON - PART 6Remember we hid the main

frame when we showed thesecond frame, so we have to re-show it. Finally we hide thesecond frame. Save yourchanges.

Here is all the code for youto verify everything (this pageand following page):

Now you can run yourapplication. If everything wentright, you will be able to clickon btnShownNew, and see thefirst frame disappear andsecond frame appear. Clickingon the Exit button on thesecond frame will cause thatframe to disappear and the

GUI2 code:

#!/usr/bin/env python#Boa:App:BoaApp

import wx

import FrameMainimport FrameSecond

modules ={u'FrameMain': [1, 'Main frame of Application',u'FrameMain.py'],u'FrameSecond': [0, '', u'FrameSecond.py']}

class BoaApp(wx.App):def OnInit(self):

self.main = FrameMain.create(None)self.main.Show()self.SetTopWindow(self.main)return True

def main():application = BoaApp(0)application.MainLoop()

if __name__ == '__main__':main()

FrameMain code:

#Boa:Frame:FrameMain

import wximport FrameSecond

def create(parent):return FrameMain(parent)

[wxID_FRAMEMAIN, wxID_FRAMEMAINBTNEXIT,wxID_FRAMEMAINBTNSHOWNEW,wxID_FRAMEMAINPANEL1,

] = [wx.NewId() for _init_ctrls in range(4)]

class FrameMain(wx.Frame):def _init_ctrls(self, prnt):

# generated method, don't editwx.Frame.__init__(self, id=wxID_FRAMEMAIN,

name=u'FrameMain',parent=prnt, pos=wx.Point(846, 177),

size=wx.Size(400, 340),style=wx.DEFAULT_FRAME_STYLE, title=u'Main

Frame')self.SetClientSize(wx.Size(400, 340))self.Center(wx.BOTH)

self.panel1 = wx.Panel(id=wxID_FRAMEMAINPANEL1,name='panel1',

parent=self, pos=wx.Point(0, 0),size=wx.Size(400, 340),

style=wx.TAB_TRAVERSAL)

self.btnShowNew =wx.Button(id=wxID_FRAMEMAINBTNSHOWNEW,

label=u'Show the other frame',name=u'btnShowNew',

parent=self.panel1, pos=wx.Point(120,103), size=wx.Size(168, 29),

style=0)self.btnShowNew.SetBackgroundColour(wx.Colour(25,

175, 23))self.btnShowNew.Bind(wx.EVT_BUTTON,

self.OnBtnShowNewButton,id=wxID_FRAMEMAINBTNSHOWNEW)

Page 27: PROGRAM IN PYTHON - Full Circledl.fullcirclemagazine.org/issuePY01_en.pdf · PROGRAMMING SERIES SPECIAL EDITION PROGRAM IN PYTHON Volume One Full Circle Magazine is neither affiliated,

full circle magazine #32 contents ^

PROGRAM IN PYTHON - PART 6FrameMain Code (cont.):

self.btnExit =wx.Button(id=wxID_FRAMEMAINBTNEXIT, label=u'Exit',

name=u'btnExit', parent=self.panel1,pos=wx.Point(162, 191),

size=wx.Size(85, 29), style=0)self.btnExit.SetBackgroundColour(wx.Colour(225,

218, 91))self.btnExit.Bind(wx.EVT_BUTTON,

self.OnBtnExitButton,id=wxID_FRAMEMAINBTNEXIT)

def __init__(self, parent):self._init_ctrls(parent)self.Fs = FrameSecond.FrameSecond(self)

def OnBtnShowNewButton(self, event):#event.Skip()self.Fs.Show()self.Hide()

def OnBtnExitButton(self, event):#event.Skip()self.Close()

FrameSecond code:#Boa:Frame:FrameSecond

import wx

def create(parent):return FrameSecond(parent)

[wxID_FRAMESECOND, wxID_FRAMESECONDBTNFSEXIT,wxID_FRAMESECONDPANEL1,wxID_FRAMESECONDSTATICTEXT1,

] = [wx.NewId() for _init_ctrls in range(4)]

class FrameSecond(wx.Frame):def _init_ctrls(self, prnt):

# generated method, don't editwx.Frame.__init__(self, id=wxID_FRAMESECOND,

name=u'FrameSecond',

parent=prnt, pos=wx.Point(849, 457),size=wx.Size(419, 236),

style=wx.DEFAULT_FRAME_STYLE, title=u'SecondFrame')

self.SetClientSize(wx.Size(419, 236))self.Center(wx.BOTH)self.SetBackgroundStyle(wx.BG_STYLE_COLOUR)

self.panel1 = wx.Panel(id=wxID_FRAMESECONDPANEL1,name='panel1',

parent=self, pos=wx.Point(0, 0),size=wx.Size(419, 236),

style=wx.TAB_TRAVERSAL)

self.btnFSExit =wx.Button(id=wxID_FRAMESECONDBTNFSEXIT, label=u'Exit',

name=u'btnFSExit', parent=self.panel1,pos=wx.Point(174, 180),

size=wx.Size(85, 29), style=0)self.btnFSExit.Bind(wx.EVT_BUTTON,

self.OnBtnFSExitButton,id=wxID_FRAMESECONDBTNFSEXIT)

self.staticText1 =wx.StaticText(id=wxID_FRAMESECONDSTATICTEXT1,

label=u"Hi there...I'm the second form!",name='staticText1',

parent=self.panel1, pos=wx.Point(45, 49),size=wx.Size(336, 23),

style=0)self.staticText1.SetFont(wx.Font(14, wx.SWISS,

wx.NORMAL, wx.BOLD,False, u'Sans'))

def __init__(self, parent):self._init_ctrls(parent)self.parent = parent

def OnBtnFSExitButton(self, event):#event.Skip()self.parent.Show()self.Hide()

Page 28: PROGRAM IN PYTHON - Full Circledl.fullcirclemagazine.org/issuePY01_en.pdf · PROGRAMMING SERIES SPECIAL EDITION PROGRAM IN PYTHON Volume One Full Circle Magazine is neither affiliated,

full circle magazine #32 contents ^

is owner of, a

consulting company in Aurora,Colorado, and has beenprogramming since 1972. Heenjoys cooking, hiking, music,and spending time with hisfamily.

PROGRAM IN PYTHON - PART 6main frame to re-appear.Clicking on the Exit button onthe main frame will close theapplication.

I promised you we'd discussnaming conventions.Remember way back, wediscussed commenting yourcode? Well, by using well-formed names for GUI controls,your code is fairly self-documenting. If you just leftcontrol names as staticText1 orbutton1 or whatever, when youare creating a complex framewith many controls, especiallyif there are a lot of text boxesor buttons, then naming themsomething that is meaningful isvery important. It might not betoo important if you are theonly one who will ever see thecode, but to someone comingbehind you later on, the goodcontrol names will help themout considerably. Therefore,use something like thefollowing:

Control type - Name prefixStatic text - st_Button - btn_Text Box - txt_Check Box - chk_Radio Button - rb_Frame - Frm_ or Frame_

You can come up with yourown ideas for namingconventions as you grow as aprogrammer, and in someinstances your employer mighthave conventions already inplace.

Next time, we will leave GUIprogramming aside for a bitand concentrate on databaseprogramming. Meanwhile, get

andloaded on your

system. You will also needand for

SQLite. If you want toexperiment with MySql as well,that's a good idea. All areavailable via Synaptic.

by Richard Redeiby Richard Redei

Page 29: PROGRAM IN PYTHON - Full Circledl.fullcirclemagazine.org/issuePY01_en.pdf · PROGRAMMING SERIES SPECIAL EDITION PROGRAM IN PYTHON Volume One Full Circle Magazine is neither affiliated,

full circle magazine #33 contents ^

HOW-TO Program In Python - Part 7

FCM#27-32 - Python Parts 1 - 6

GraphicsDev Internet M/media System

HDDCD/DVD USB Drive Laptop Wireless

Good morning Boysand Girls. It's storytime. Everyone getsettled and comfy.

Ready? Good!

Once upon a time, the worldwas ruled by paper. Paper,paper everywhere. They had tomake special homes for all thatpaper. They were called filingcabinets, and were big metalthings that would take roomsand rooms and rooms atbusinesses to house all the

paper. In each filing cabinetwas something called a filefolder, which attempted toorganize relevant paperstogether. But after time, theywould get over-stuffed, and fallapart when they got old oropened too many times.

Using these filing cabinetsproperly required a collegedegree. It could take days tofind all the papers that were inthe various cabinets.Businesses suffered horribly. Itwas a very dark time in thehistory of man- and woman-kind.

Then one day, from the topof a mountain somewhere (Ipersonally think it wasColorado, but I'm not sure),came a lovely fairy. This fairywas blue and silver - withbeautiful wings and white hair,and was about 1 foot tall. Hername, believe it or not, wasSee-Quill. Isn't that a funnyname? Anyway, See-Quill saidthat she could fix everythinghaving to do with all the paper

and filing cabinets and wastedtime, if only people wouldbelieve in computers and her.She called this power a“Database”. She said that the“Database” could replace theentire filing system. Somepeople did, and soon their liveswere very happy. Some didn't,and their lives stayed thesame, lost in mountains ofpaper.

All fairy promises, however,come with some sort ofrequirement. That requirementwas that whoever wanted touse the power of See-Quillneeded to learn a bit of adifferent language. It wouldn'tbe too difficult a language tolearn. In fact, it was much likethe one the people alreadyused. It just has a different wayof saying things, and you hadto think about things verycarefully BEFORE you saidthem - to use the power of See-Quill.

One day, a young boynamed, curiously enough,

User, came to see See-Quill.He was very impressed withher beauty, and said “See-Quill, Please teach me to useyour power.” See-Quill saidthat she would.

She said, “First, you have toknow how your information islaid out. Show me your papers.”

Being a young boy, Userhad only a few pieces of paper.See-Quill said, “User, right nowyou could live with papers andfile folders. However, I can getglimpses of the future, and youwill someday have so manypapers that they would, ifplaced on top of each other, betaller than you by 15 times. Weshould use my power.”

So, working together, Userand See-Quill created a“database thingie” (a fairytechnical term), and User livedhappily ever after.

Of course, the story is not

Page 30: PROGRAM IN PYTHON - Full Circledl.fullcirclemagazine.org/issuePY01_en.pdf · PROGRAMMING SERIES SPECIAL EDITION PROGRAM IN PYTHON Volume One Full Circle Magazine is neither affiliated,

full circle magazine #33 contents ^

PROGRAM IN PYTHON - PART 7completely true. However,using databases and SQL canmake our lives easier. Thistime, we will learn about somesimple SQL queries, and how touse them in a program. Somepeople might think that thismight not be the “correct” wayor the “best” way, but it is areasonable way. So let's begin.

Databases are like the filingcabinets in our story above.Data tables are like the filefolders. The individual recordsin the tables are like the sheetsof paper. Each piece ofinformation is called a field. Itfalls together very nicely,doesn't it? You use SQL(pronounced See-Quill)statements to do things withthe data. SQL stands forStructured Query Language,and is basically designed to bean easy way to use databases.In practice, however, it canbecome very complicated. Wewill keep things pretty simplefor this installment.

We need to create a plan,like starting any constructionproject. So, think of a recipecard, which is a good thing tothink about, since we are going

to create a recipe databaseprogram. Around my house,recipes come in various forms:3x5 card, 8x10 pieces of paper,napkins with the recipescribbled on it, pages frommagazines, and even strangerforms. They can be found inbooks, boxes, binders, andother things. However, they allpretty much have one thing incommon: the format. In almostevery case, at the top you havethe recipe title and maybe howmany servings it makes andwhere it came from. Themiddle contains the list ofingredients, and the bottomcontains the instructions -dealing with the order thatthings are done in, the cookingtime, and so on. We will usethis general format as thetemplate of our databaseproject. We will break this upinto two parts. We'll create thedatabase this time, and theapplication to read and updatethe database next time.

Here's an example. Let's saywe have the recipe shown right.

Notice the order we justdiscussed. Now when wedesign our database - we could

make it very large andhave one record foreverything in the recipe.That, however, would beclumsy and hard to dealwith. Instead, we are goingto use the recipe card as atemplate. One table willhandle the top of the card,or the gross informationabout the recipe; one tablewill handle the middle ofthe card, or the ingredientsinformation; and one tablewill handle the bottom, orthe instructions.

Make sure you haveinstalled SQLite and APSW.SQLite is a small databaseengine that doesn't requireyou to have a separatedatabase server, whichmakes it ideal for our littleapplication. Everything youlearn here can be usedwith larger databasesystems like MySQL andothers. The other goodthing about SQLite is thatit uses limited data types.These types are Text,Numeric, Blob, and IntegerPrimary Key. As you havelearned already, text ispretty much anything. Our

Serves: 4

: Greg Walters

1 cup parboiled Rice (uncooked)1 pound Hamburger2 cups Water1 8 oz can Tomato Sauce1 small Onion chopped1 clove Garlic chopped1 tablespoon Ground Cumin1 teaspoon Ground OreganoSalt and Pepper to tasteSalsa to taste

Brown hamburger.

Add all other ingredients.

Bring to boil.

Stir, lower to simmer and cover.

Cook for 20 minutes.

Do not look, do not touch.

Stir and serve.

Page 31: PROGRAM IN PYTHON - Full Circledl.fullcirclemagazine.org/issuePY01_en.pdf · PROGRAMMING SERIES SPECIAL EDITION PROGRAM IN PYTHON Volume One Full Circle Magazine is neither affiliated,

full circle magazine #33 contents ^

PROGRAM IN PYTHON - PART 7ingredients, instructions, andthe title of our recipe are alltext types - even though theyhave numbers in them.Numeric datatypes storenumbers. These can be integervalues or floating point or realvalues. Blobs are binary data,and can include things likepictures and other things.Integer Primary Key values arespecial. The SQLite databaseengine automatically puts in aguaranteed unique integervalue for us. This will beimportant later on.

APSW stands for AnotherPython SQLite Wrapper and is aquick way to communicate withSQLite. Now let's go over someof the ways to create our SQLstatements.

To obtain records from adatabase, you would use theSELECT statement. The formatwould be:

SELECT [what] FROM [whichtable(s)] WHERE [Constraints]

So, if we want to get all thefields from the Recipes tablewe would use:

SELECT * FROM Recipes

If you wish to obtain just arecord by its primary key, youhave to know what that valueis (pkID in this instance), andwe have to include a WHEREcommand in the statement. Wecould use:

SELECT * FROM Recipes WHEREpkID = 2

Simple enough...right?Pretty much plain language.Now, suppose we want to justget the name of the recipe andthe number of servings itmakes - for all recipes. It'seasy. All you have to do isinclude a list of the fields thatyou want in the SELECTstatement:

SELECT name, servings FROMRecipes

To insert records, we use theINSERT INTO command. Thesyntax is

INSERT INTO [table name](field list) VALUES (valuesto insert)

So, to insert a recipe intothe recipe table the command

would be

INSERT INTO Recipes(name,servings,source)VALUES (“Tacos”,4,”Greg”)

To delete a record we canuse

DELETE FROM Recipes WHEREpkID = 10

There's also an UPDATEstatement, but we'll leave thatfor another time.

More on SELECTIn the case of our database,

we have three tables, each canbe related together by usingrecipeID pointing to the pkID ofthe recipe table. Let's say wewant to get all the instructionsfor a given recipe. We can do itlike this:

SELECT Recipes.name,Recipes.servings,Recipes.source,Instructions.InstructionsFROM Recipes LEFT JOINinstructions ON(Recipes.pkid =Instructions.recipeid) WHERERecipes.pkid = 1

However, that is a lot of

typing and very redundant. Wecan use a method calledaliasing. We can do it like this:

SELECT r.name, r.servings,r.source, i.InstructionsFROM Recipes r LEFT JOINinstructions i ON (r.pkid =i.recipeid) WHERE r.pkid = 1

It's shorter and stillreadable. Now we will write asmall program that will createour database, create ourtables, and put some simpledata into the tables to havesomething to work with. WeCOULD write this into our fullprogram, but, for this example,we will make a separateprogram. This is a run-onceprogram - if you try to run it asecond time, it will fail at thetable creation statements.Again, we could wrap it with atry...catch handler, but we'll dothat another time.

We start by importing theAPSW wrapper.

import apsw

The next thing we need todo is create a connection to ourdatabase. It will be located inthe same directory where we

Page 32: PROGRAM IN PYTHON - Full Circledl.fullcirclemagazine.org/issuePY01_en.pdf · PROGRAMMING SERIES SPECIAL EDITION PROGRAM IN PYTHON Volume One Full Circle Magazine is neither affiliated,

full circle magazine #33 contents ^

PROGRAM IN PYTHON - PART 7have our application. When wecreate this connection, SQLiteautomatically looks to see ifthe database exists. If so, itopens it. If not, it creates thedatabase for us. Once we havea connection, we need what iscalled a cursor. This creates amechanism that we can use towork with the database. Soremember, we need both aconnection and a cursor. Theseare created like this:

# Opening/creating database

connection=apsw.Connection("cookbook1.db3")cursor=connection.cursor()

Okay - we have ourconnection and our cursor. Nowwe need to create our tables.There will be three tables inour application. One to hold thegross recipe information, onefor the instructions for eachrecipe, and one to hold the listof the ingredients. Couldn't wedo it with just one table? Well,yes we could, but, as you willsee, it will make that one tablevery large, and will include abunch of duplicate information.

We can look at the table

structure like this. Each columnis a separate table as shownabove right.

Each table has a field calledpkID. This is the primary keythat will be unique within thetable. This is important so thatthe data tables never have acompletely duplicated record.This is an integer data type,and is automatically assignedby the database engine. Canyou do without it? Yes, but yourun the risk of accidentallycreating a duplicated record id.In the case of the Recipestable, we will use this numberas a reference for whichinstruction and which set ofingredients go with that recipe.

We would first put theinformation into the databaseso that the name, source andnumber served goes into therecipe table. The pkID is

automatically assigned. Let'spretend that this is the veryfirst record in our table, so thedatabase engine would assignthe value 1 to the pkID. We willuse this value to relate theinformation in the other tablesto this recipe. The instructionstable is simple. It just holds thelong text of the instructions, itsown pkID and then a pointer tothe recipe in the recipe table.The ingredients table is a bitmore complicated in that wehave one record for eachingredient as well as its ownpkID and the pointer back toour recipe table record.

So in order to create therecipe table, we define a stringvariable called sql, and assignit the command to create thetable:

sql = 'CREATE TABLE Recipes(pkiD INTEGER PRIMARY KEY,name TEXT, servings TEXT,

source TEXT)'

Next we have to tell ASPWto actually do the sql command:

cursor.execute(sql)

Now we create the othertables:

sql = 'CREATE TABLEInstructions (pkID INTEGERPRIMARY KEY, instructionsTEXT, recipeID NUMERIC)'

cursor.execute(sql)

sql = 'CREATE TABLEIngredients (pkID INTEGERPRIMARY KEY, ingredientsTEXT, recipeID NUMERIC)'

cursor.execute(sql)

Once we have the tablescreated, we will use the INSERTINTO command to enter eachset of data into its proper table.

Remember, the pkID is

RECIPES INSTRUCTIONS INGREDIENTS------------ ---------------------- --------------------pkID (Integer Primary Key) pkID(Integer Primary Key) pkID (Integer Primary Key)name (Text) recipeID (Integer) recipeID (Integer)source (Text) instructions (Text) ingredients (Text)serves (Text)

Page 33: PROGRAM IN PYTHON - Full Circledl.fullcirclemagazine.org/issuePY01_en.pdf · PROGRAMMING SERIES SPECIAL EDITION PROGRAM IN PYTHON Volume One Full Circle Magazine is neither affiliated,

full circle magazine #33 contents ^

is owner of, a

consulting company in Aurora,Colorado, and has beenprogramming since 1972. Heenjoys cooking, hiking, music,and spending time with hisfamily.

PROGRAM IN PYTHON - PART 7automatically entered for us,so we don't include that in thelist of fields in our insertstatement. Since we will beusing the field names, they canbe in any order, not just theorder they were created in. Aslong as we know the names ofthe fields, everything will workcorrectly. The insert statementfor our recipe table entrybecomes

INSERT INTO Recipes (name,serves, source) VALUES(“Spanish Rice”,4,”GregWalters”)

Next we need to find out thevalue that was assigned to thepkID in the recipe table. Wecan do this with a simplecommand:

SELECT last_insert_rowid()

However, it doesn't justcome out as something we canreally use. We need to use aseries of statements like this:

sql = "SELECTlast_insert_rowid()"

cursor.execute(sql)

for x in cursor.execute(sql):lastid = x[0]

Why is this? Well, when weget data back from ASPW, itcomes back as a tuple. This issomething we haven't talkedabout yet. The quickexplanation is that a tuple is (ifyou look at the code above)like a list, but it can't bechanged. Many people usetuples rarely; others use themoften; it's up to you. Thebottom line is that we want touse the first value returned. Weuse the 'for' loop to get thevalue into the tuple variable x.Make sense? OK. Let'scontinue...

Next, we would create theinsert statement for theinstructions:

sql = 'INSERT INTOInstructions(recipeID,instructions)VALUES( %s,"Brown hamburger.Stir in all otheringredients. Bring to aboil. Stir. Lower to simmer.Cover and cook for 20minutes or until all liquidis absorbed.")' % lastid

cursor.execute(sql)

Notice that we are using thevariable substitution (%s) to

place the pkID of the recipe(lastid) into the sql statement.Finally, we need to put eachingredient into the ingredienttable. I'll show you just one fornow:

sql = 'INSERT INTOIngredients(recipeID,ingredients)VALUES ( %s,"1 cup parboiledRice (uncooked)")' % lastid

cursor.execute(sql)

It's not too hard tounderstand at this point. Nexttime it will get a bit morecomplicated.

If you would like the fullsource code, I've placed it onmy website. Go towww.thedesignatedgeek.comto download it.

Next time, we will use whatwe've learned over the seriesto create a menu-driven frontend for our recipe program - itwill allow viewing all recipes ina list format, viewing a singlerecipe, searching for a recipe,and adding and deletingrecipes.

I suggest that you spend

some time reading up on SQLprogramming. You'll be happyyou did.

Page 34: PROGRAM IN PYTHON - Full Circledl.fullcirclemagazine.org/issuePY01_en.pdf · PROGRAMMING SERIES SPECIAL EDITION PROGRAM IN PYTHON Volume One Full Circle Magazine is neither affiliated,

full circle magazine #34 contents ^

HOW-TO Program In Python - Part 8

FCM#27-33 - Python Parts 1 - 7

GraphicsDev Internet M/media System

HDDCD/DVD USB Drive Laptop Wireless

Wewill continueprogramming ourrecipe databasethat we started in

Part 7. This will be a long one,with a lot of code, so grab onwith all your might and don't letgo. But remember, keep yourhands and feet inside the car atall times. We have alreadycreated our database. Now wewant to display the contents,add to it and delete from it. Sohow do we do that? We willstart with an application that

runs in a terminal, so we needto create a menu. We will alsocreate a class that will holdour database routines. Let'sstart with a stub of ourprogram shown above right.

Now we will layout ourmenu. We do that so we canstub our class. Our menu willbe a rather big loop that willdisplay a list of options thatthe user can perform. We'lluse a while loop. Change themenu routine to look like thecode shown below right.

Next we stub the menu withan if|elif|else structure whichis shown at the top of the nextpage.

Let's take a quick look atour menu routine. We start offby printing the prompts thatthe user can perform. We set avariable (loop) to True, andthen use the while function tocontinue looping until loop =False. We use the raw_input()command to wait for the userto select an option, and then

#!/usr/bin/python#------------------------------------------------------# Cookbook.py# Created for Beginning Programming Using Python #8# and Full Circle Magazine#------------------------------------------------------import apswimport stringimport webbrowser

class Cookbook:

def Menu():cbk = Cookbook() # Initialize the class

Menu()

def Menu():cbk = Cookbook() # Initialize the classloop = Truewhile loop == True:

print'==================================================='

print ' RECIPE DATABASE'print

'==================================================='print ' 1 - Show All Recipes'print ' 2 - Search for a recipe'print ' 3 - Show a Recipe'print ' 4 - Delete a recipe'print ' 5 - Add a recipe'print ' 6 - Print a recipe'print ' 0 - Exit'print

'==================================================='response = raw_input('Enter a selection -> ')

Page 35: PROGRAM IN PYTHON - Full Circledl.fullcirclemagazine.org/issuePY01_en.pdf · PROGRAMMING SERIES SPECIAL EDITION PROGRAM IN PYTHON Volume One Full Circle Magazine is neither affiliated,

full circle magazine #34 contents ^

PROGRAM IN PYTHON - PART 8

our if routine to handlewhichever option the userselected. Before we can runthis for a test, we need tocreate a stub inside our classfor the __init__ routine:

def __init__(self):pass

Now, save your programwhere you saved the databaseyou created from the last time,and run it. You should seesomething like that shownabove right.

It should simply print themenu over and over, until you

type “0”, and then print“Goodbye” and exit. At thispoint, we can now start stubsof our routines in the Cookbookclass. We will need a routinethat will display all theinformation out of the Recipesdata table, one that will allowyou to search for a recipe, onethat will show the data for asingle recipe from all threetables, one that will delete arecipe, one that will allow youto add a recipe, and one thatwill print the recipe to thedefault printer. ThePrintAllRecipes routine doesn'tneed a parameter other thanthe (self) parameter, neitherdoes the SearchforRecipe nor

the EnterNew routines. ThePrintSingleRecipe,DeleteRecipe and PrintOutroutines all need to know whatrecipe to deal with, so they willneed to have a parameter thatwe'll call “which”. Use the passcommand to finish each stub.Under the Cookbook class,create the routine stubs:

def PrintAllRecipes(self):pass

def SearchForRecipe(self):pass

defPrintSingleRecipe(self,which):

passdef DeleteRecipe(self,which):

passdef EnterNew(self):

passdef PrintOut(self,which):

pass

For a number of the menu

items, we will want to print outall of the recipes from theRecipe table – so the user canpick from that list. These willbe options 1, 3, 4 and 6. So,modify the menu routine forthose options, replacing thepass command withcbk.PrintAllRecipes(). Ourresponse check routine willnow look like the code at thetop of the next page.

One more thing to do is toset up the __init__ routine.Replace the stub with thefollowing lines:

def __init__(self):global connectionglobal cursorself.totalcount = 0connection=apsw.Connection(

"cookbook.db3")cursor=connection.cursor()

if response == '1': # Show all recipespass

elif response == '2': # Search for a recipepass

elif response == '3': # Show a single recipepass

elif response == '4': # Delete Recipepass

elif response == '5': # Add a recipepass

elif response == '6': # Print a recipepass

elif response == '0': # Exit the programprint 'Goodbye'loop = False

else:print 'Unrecognized command. Try again.'

/usr/bin/python -u"/home/greg/python_examples/APSW/cookbook/cookbook_stub.py"===================================================

RECIPE DATABASE===================================================1 - Show All Recipes2 - Search for a recipe3 - Show a Recipe4 - Delete a recipe5 - Add a recipe6 - Print a recipe0 - Exit===================================================Enter a selection ->

Page 36: PROGRAM IN PYTHON - Full Circledl.fullcirclemagazine.org/issuePY01_en.pdf · PROGRAMMING SERIES SPECIAL EDITION PROGRAM IN PYTHON Volume One Full Circle Magazine is neither affiliated,

full circle magazine #34 contents ^

PROGRAM IN PYTHON - PART 8

First we create two globalvariables for our connectionand cursor. We can accessthem from anywhere within thecookbook class. Next, wecreate a variable self.totalcountwhich we use to count thenumber of recipes. We'll beusing this variable later on.Finally we create theconnection and the cursor.

The next step will be to fleshout the PrintAllRecipes()routine in the Cookbook class.Since we have the globalvariables for connection andcursor, we don't need to re-create them in each routine.

Next, we will want to do a“pretty print” to the screen forheaders for our recipe list. We'lluse the “%s” formattingcommand, and the left justifycommand, to space out ourscreen output. We want it tolook like this:

Item Name Serves Source

---------------------------

Finally, we need to createour SQL statement, query thedatabase, and display theresults. Most of this wascovered in the article last time.

sql = 'SELECT * FROM

Recipes'cntr = 0for x in

cursor.execute(sql):cntr += 1print '%s %s %s %s'

%(str(x[0]).rjust(5),x[1].ljust(30),x[2].ljust(20),x[3].ljust(30))

print '-------------'self.totalcount = cntr

The cntr variable will countthe number of recipes wedisplay to the user. Now ourroutine is done. Shown below isthe full code for the routine,just in case you missedsomething.

Notice that we are using thetuple that is returned from thecursor.execute routine fromASPW. We are printing the pkID

as the item for each recipe.This will allow us to select thecorrect recipe later on. Whenyou run your program, youshould see the menu, andwhen you select option 1, you'llget what's shown at the top ofthe next page.

That's what we wanted,except if you are running theapp in Dr.Python or the like, theprogram doesn't pause. Let'sadd a pause until the userpresses a key so they can lookat the output for a second ortwo. While we are at it, let'sprint out the total number ofrecipes from the variable weset up a moment ago. Add tothe bottom of option 1 of themenu:

if response == '1': # Show all recipescbk.PrintAllRecipes()

elif response == '2': # Search for a recipepass

elif response == '3': # Show a single recipecbk.PrintAllRecipes()

elif response == '4': # Delete Recipecbk.PrintAllRecipes()

elif response == '5': # Add a recipepass

elif response == '6': # Print a recipecbk.PrintAllRecipes()

elif response == '0': # Exit the programprint 'Goodbye'loop = False

else:print 'Unrecognized command. Try again.'

def PrintAllRecipes(self):print '%s %s %s %s'

%('Item'.ljust(5),'Name'.ljust(30),'Serves'.ljust(20),'Source'.ljust(30))

print '---------------------------------'sql = 'SELECT * FROM Recipes'cntr = 0for x in cursor.execute(sql):

cntr += 1print '%s %s %s %s'

%(str(x[0]).rjust(5),x[1].ljust(30),x[2].ljust(20),x[3].ljust(30))

print '---------------------------------'self.totalcount = cntr

Page 37: PROGRAM IN PYTHON - Full Circledl.fullcirclemagazine.org/issuePY01_en.pdf · PROGRAMMING SERIES SPECIAL EDITION PROGRAM IN PYTHON Volume One Full Circle Magazine is neither affiliated,

full circle magazine #34 contents ^

PROGRAM IN PYTHON - PART 8

print 'Total Recipes - %s'%cbk.totalcount

print '----------------------------------------------------'

res = raw_input('Press A Key-> ')

We'll skip option #2 (Searchfor a recipe) for a moment, anddeal with #3 (Show a singlerecipe). Let's deal with themenu portion first. We'll showthe list of recipes, as for option1, and then ask the user toselect one. To make sure wedon't get errors due to a bad

user input, we'll use theTry|Except structure. We willprint the prompt to the user(Select a recipe → ), then, ifthey enter a correct response,we'll call thePrintSingleRecipe() routine inour Cookbook class with thepkID from our Recipe table. Ifthe entry is not a number, itwill raise a ValueErrorexception, which we handlewith the except ValueError:catch shown right.

Next, we'll work on ourPrintSingleRecipe routine in theCookbook class. We start with

the connection and cursoragain, then create our SQLstatement. In this case, we use'SELECT * FROM RecipesWHERE pkID = %s” %str(which)' where which is thevalue we want to find. Then we“pretty print” the output, again

from the tuple returned byASPW. In this case, we use x asthe gross variable, and theneach one with bracketed indexinto the tuple. Since the tablelayout ispkID/name/servings/source, wecan use x[0],x[1],x[2] and x[3]as the detail. Then, we want toselect everything from theingredients table where therecipeID (our key into therecipes data table) is equal tothe pkID we just used. We loopthrough the tuple returned,printing each ingredient, andthen finally we get theinstructions from theinstructions table – just like wedid for the ingredients table.Finally, we wait for the user topress a key so they can see therecipe on the screen. The codeis shown on the next page.

Now, we have two routines

Enter a selection -> 1Item Name Serves Source--------------------------------------------------------------------------------------

1 Spanish Rice 4 Greg2 Pickled Pepper-Onion Relish 9 half pints Complete Guide to Home Canning

--------------------------------------------------------------------------------------===================================================

RECIPE DATABASE===================================================1 - Show All Recipes2 - Search for a recipe3 - Show a Recipe4 - Delete a recipe5 - Add a recipe6 - Print a recipe0 - Exit===================================================Enter a selection ->

try:res = int(raw_input('Select a Recipe -> '))if res <= cbk.totalcount:

cbk.PrintSingleRecipe(res)elif res == cbk.totalcount + 1:

print 'Back To Menu...'else:

print 'Unrecognized command. Returning to menu.'except ValueError:

print 'Not a number...back to menu.'

Page 38: PROGRAM IN PYTHON - Full Circledl.fullcirclemagazine.org/issuePY01_en.pdf · PROGRAMMING SERIES SPECIAL EDITION PROGRAM IN PYTHON Volume One Full Circle Magazine is neither affiliated,

full circle magazine #34 contents ^

PROGRAM IN PYTHON - PART 8out of the six finished. So, let'sdeal with the search routine,again starting with the menu.Luckily this time, we just callthe search routine in the class,so replace the pass commandwith:

cbk.SearchForRecipe()

Now to flesh out our searchcode. In the Cookbook class,replace our stub for theSearchForRecipe with the codeshown on the next page.

There's a lot going on there.After we create our connectionand cursor, we display oursearch menu. We are going togive the user three ways tosearch, and a way to exit theroutine. We can let the usersearch by a word in the recipename, a word in the recipesource, or a word in theingredient list. Because of this,we can't just use the displayroutine we just created, andwill need to create customprintout routines. The first twooptions use simple SELECTstatements with an addedtwist. We are using the “like”qualifier. If we were using aquery browser like SQLite

Database Browser, our likestatement uses a wildcardcharacter of “%”. So, to lookfor a recipe containing “rice” inthe recipe name, our querywould be:

SELECT * FROM Recipes WHEREname like '%rice%'

However, since the “%”character is also a substitutioncharacter in our strings, wehave to use %% in our text. Tomake it worse, we are usingthe substitution character toinsert the word the user issearching for. Therefore, wemust make it '%%%s%%'.Sorry if this is as clear as mud.The third query is called a Joinstatement. Let's look at it a bitcloser:

sql = "SELECTr.pkid,r.name,r.servings,r.source,i.ingredients FROMRecipes r Left Joiningredients i on (r.pkid =i.recipeid) WHEREi.ingredients like '%%%s%%'GROUP BY r.pkid" %response

We are selecting everythingfrom the recipe table, and theingredients from theingredients table, joining orrelating the ingredient table

ON the recipeID being equal tothe pkID in the recipe table,then searching for ouringredient using the likestatement, and, finally,grouping the result by the pkIDin the recipe table to keepduplicates from being shown. Ifyou remember, we havepeppers twice in the secondrecipe (Onion and pepperrelish), one green and one red.

That could create confusion inour user's mind. Our menu uses

searchin =raw_input('Enter Search Type-> ')

if searchin != '4':

which says: if searchin (thevalue the user entered) is NOTequal to 4 then do the options,if it is 4, then don't do

def PrintSingleRecipe(self,which):sql = 'SELECT * FROM Recipes WHERE pkID = %s' %

str(which)print

'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~'for x in cursor.execute(sql):

recipeid =x[0]print "Title: " + x[1]print "Serves: " + x[2]print "Source: " + x[3]

print'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~'

sql = 'SELECT * FROM Ingredients WHERE RecipeID= %s' % recipeid

print 'Ingredient List:'for x in cursor.execute(sql):

print x[1]print ''print 'Instructions:'sql = 'SELECT * FROM Instructions WHERE RecipeID

= %s' % recipeidfor x in cursor.execute(sql):

print x[1]print

'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~'resp = raw_input('Press A Key -> ')

Page 39: PROGRAM IN PYTHON - Full Circledl.fullcirclemagazine.org/issuePY01_en.pdf · PROGRAMMING SERIES SPECIAL EDITION PROGRAM IN PYTHON Volume One Full Circle Magazine is neither affiliated,

full circle magazine #34 contents ^

def SearchForRecipe(self):# print the search menuprint '-------------------------------'print ' Search in'print '-------------------------------'print ' 1 - Recipe Name'print ' 2 - Recipe Source'print ' 3 - Ingredients'print ' 4 - Exit'searchin = raw_input('Enter Search Type -> ')if searchin != '4':

if searchin == '1':search = 'Recipe Name'

elif searchin == '2':search = 'Recipe Source'

elif searchin == '3':search = 'Ingredients'

parm = searchinresponse = raw_input('Search for what in %s (blank to exit) -> ' % search)if parm == '1': # Recipe Name

sql = "SELECT pkid,name,source,servings FROM Recipes WHERE name like '%%%s%%'" %responseelif parm == '2': # Recipe Source

sql = "SELECT pkid,name,source,servings FROM Recipes WHERE source like '%%%s%%'" %responseelif parm == '3': # Ingredients

sql = "SELECT r.pkid,r.name,r.servings,r.source,i.ingredients FROM Recipes r Left Join ingredients ion (r.pkid = i.recipeid) WHERE i.ingredients like '%%%s%%' GROUP BY r.pkid" %response

try:if parm == '3':

print '%s %s %s %s %s'%('Item'.ljust(5),'Name'.ljust(30),'Serves'.ljust(20),'Source'.ljust(30),'Ingredient'.ljust(30))

print '--------------------------------------------------------------------------------------'else:

print '%s %s %s %s' %('Item'.ljust(5),'Name'.ljust(30),'Serves'.ljust(20),'Source'.ljust(30))print '--------------------------------------------------------------------------------------'

for x in cursor.execute(sql):if parm == '3':

print '%s %s %s %s %s'%(str(x[0]).rjust(5),x[1].ljust(30),x[2].ljust(20),x[3].ljust(30),x[4].ljust(30))

else:print '%s %s %s %s' %(str(x[0]).rjust(5),x[1].ljust(30),x[3].ljust(20),x[2].ljust(30))

except:print 'An Error Occured'

print '--------------------------------------------------------------------------------------'inkey = raw_input('Press a key')

Page 40: PROGRAM IN PYTHON - Full Circledl.fullcirclemagazine.org/issuePY01_en.pdf · PROGRAMMING SERIES SPECIAL EDITION PROGRAM IN PYTHON Volume One Full Circle Magazine is neither affiliated,

full circle magazine #34 contents ^

PROGRAM IN PYTHON - PART 8anything, just fall through.Notice that I used “!=” as NotEqual To instead of “<>”.Either will work under Python2.x. However, in Python 3.x, itwill give a syntax error. We'llcover more Python 3.xchanges in a future article. Fornow, start using “!=” to makeyour life easier to move toPython 3.x in the future.Finally, we “pretty print” againour output. Let's look at whatthe user will see, shown right.

You can see how nicely theprogram prints the output.Now, the user can go back tothe menu and use option #3 toprint whichever recipe theywant to see. Next we will addrecipes to our database. Again,we just have to add one line toour menu routine, the call tothe EnterNew routine:

cbk.EnterNew()

The code that needs toreplace the stub in theCookbook class for EnterNew()is at:http://pastebin.com/f1d868e63.

We start by defining a listnamed “ings” – which stands

Enter a selection -> 2-------------------------------Search in-------------------------------1 - Recipe Name2 - Recipe Source3 - Ingredients4 - ExitEnter Search Type -> 1Search for what in Recipe Name (blank to exit) -> riceItem Name Serves Source--------------------------------------------------------------------------------------

1 Spanish Rice 4 Greg--------------------------------------------------------------------------------------Press a key

Easy enough. Now for the ingredient search...

Enter a selection -> 2-------------------------------Search in-------------------------------1 - Recipe Name2 - Recipe Source3 - Ingredients4 - ExitEnter Search Type -> 3Search for what in Ingredients (blank to exit) -> onionItem Name Serves Source Ingredient

--------------------------------------------------------------------------------------1 Spanish Rice 4 Greg 1 smallOnion chopped2 Pickled Pepper-Onion Relish 9 half pints Complete Guide to Home Canning 6 cupsfinely chopped Onions--------------------------------------------------------------------------------------Press a key

Page 41: PROGRAM IN PYTHON - Full Circledl.fullcirclemagazine.org/issuePY01_en.pdf · PROGRAMMING SERIES SPECIAL EDITION PROGRAM IN PYTHON Volume One Full Circle Magazine is neither affiliated,

full circle magazine #34 contents ^

PROGRAM IN PYTHON - PART 8for ingredients. We then askthe user to enter the title,source, and servings. We thenenter a loop, asking for eachingredient, appending to theing list. If the user enters 0, weexit the loop and continue onasking for the instructions. Wethen show the recipe contentsand ask the user to verifybefore saving the data. We useINSERT INTO statements, likewe did last time, and return tothe menu. One thing we haveto be careful of is the singlequote in our entries. USUALLY,this won't be a problem in theingredient list or theinstructions, but in our title orsource fields, it could come up.We need to add an escapecharacter to any single quotes.We do this with thestring.replace routine, which iswhy we imported the stringlibrary. In the menu routine,put the code shown aboveright under option #4.

Then, in the Cookbook class,use the code shown belowright for the DeleteRecipe()routine.

Quickly, we'll go through thedelete routine. We first ask the

user which recipe to delete(back in the menu), and passthat pkID number into ourdelete routine. Next, we askthe user 'are they SURE' theywant to delete the recipe. If theresponse is “Y”(string.upper(resp) == 'Y'),then we create the sql deletestatements. Notice that thistime we have to delete recordsfrom all three tables. Wecertainly could just delete therecord from the recipes table,but then we'd have orphanrecords in the other two, andthat wouldn't be good. Whenwe delete the record from therecipe table, we use the pkIDfield. In the other two tables,we use the recipeID field.

Finally, we will deal with theroutine to print the recipes.We'll be creating a VERY simpleHTML file, opening the defaultbrowser and allowing them toprint from there. This is why weare importing the webbrowserlibrary. In the menu routine foroption #6, insert the codeshown at the top of the nextpage.

Again, we display a list of allthe recipes, and allow them to

select the one that they wish toprint. We call the PrintOutroutine in the Cookbook class.That code is shown at the topright of the next page.

We start with the fi =

open([filename],'w') commandwhich creates the file. We thenpull the information from therecipe table, and write it to thefile with the fi.write command.We use the <H1></H1>header 1 tag for the title, the

cbk.PrintAllRecipes()print '0 - Return To Menu'try:

res = int(raw_input('Select a Recipe to DELETEor 0 to exit -> '))

if res != 0:cbk.DeleteRecipe(res)

elif res == '0':print 'Back To Menu...'

else:print 'Unrecognized command. Returning to

menu.'except ValueError:

print 'Not a number...back to menu.'

def DeleteRecipe(self,which):resp = raw_input('Are You SURE you want to

Delete this record? (Y/n) -> ')if string.upper(resp) == 'Y':

sql = "DELETE FROM Recipes WHERE pkID = %s"% str(which)

cursor.execute(sql)sql = "DELETE FROM Instructions WHERE

recipeID = %s" % str(which)cursor.execute(sql)sql = "DELETE FROM Ingredients WHERE

recipeID = %s" % str(which)cursor.execute(sql)print "Recipe information DELETED"resp = raw_input('Press A Key -> ')

else:print "Delete Aborted - Returning to menu"

Page 42: PROGRAM IN PYTHON - Full Circledl.fullcirclemagazine.org/issuePY01_en.pdf · PROGRAMMING SERIES SPECIAL EDITION PROGRAM IN PYTHON Volume One Full Circle Magazine is neither affiliated,

full circle magazine #34 contents ^

is owner of, a

consulting company in Aurora,Colorado, and has beenprogramming since 1972. Heenjoys cooking, hiking, music,and spending time with hisfamily.

PROGRAM IN PYTHON - PART 8<H2> tag for servings andsource. We then use the<li></li> list tags for ouringredient list, and then writethe instructions. Other thanthat it's simple queries we'vealready learned. Finally, weclose the file with the fi.close()command, and usewebbrowser.open([filename])with the file we just created.The user can then print fromtheir web browser – if required.

This was ourbiggest application to date. I'veposted the full source code(and the sample database ifyou missed last month) on mywebsite. If you don't want totype it all in or have anyproblems, then hop over to myweb site,www.thedesignatedgeek.comto get the code.

cbk.PrintAllRecipes()print '0 - Return To Menu'try:

res = int(raw_input('Select a Recipe to DELETE or 0 to exit -> '))if res != 0:

cbk.PrintOut(res)elif res == '0':

print 'Back To Menu...'else:

print 'Unrecognized command. Returning to menu.'except ValueError:

print 'Not a number...back to menu.'

def PrintOut(self,which):fi = open('recipeprint.html','w')sql = "SELECT * FROM Recipes WHERE pkID = %s" % whichfor x in cursor.execute(sql):

RecipeName = x[1]RecipeSource = x[3]RecipeServings = x[2]

fi.write("<H1>%s</H1>" % RecipeName)fi.write("<H2>Source: %s</H2>" % RecipeSource)fi.write("<H2>Servings: %s</H2>" % RecipeServings)fi.write("<H3> Ingredient List: </H3>")sql = 'SELECT * FROM Ingredients WHERE RecipeID = %s' % whichfor x in cursor.execute(sql):

fi.write("<li>%s</li>" % x[1])fi.write("<H3>Instructions:</H3>")sql = 'SELECT * FROM Instructions WHERE RecipeID = %s' % whichfor x in cursor.execute(sql):

fi.write(x[1])fi.close()webbrowser.open('recipeprint.html')print "Done"