Advance Python Programming

Download as pdf or txt
Download as pdf or txt
You are on page 1of 184

e

ut
ib
tr
is
D
STUDENT MANUAL
or
Python®
e
at

Programming:
lic

Advanced
up
D
ot
N
o
D
e
ut
Python®

ib
tr
Programming:

is
D
Advanced
or
e
at
lic
up
D
ot
N
o
D
Python® Programming: Advanced

e
Part Number: 094012

ut
Course Edition: 1.0

Acknowledgements

ib
PROJECT TEAM

tr
Author Media Designer Content Editor

is
Richard K. Blum Brian Sullivan Michelle Farney

D
Notices
DISCLAIMER

or
While Logical Operations, Inc. takes care to ensure the accuracy and quality of these materials, we cannot guarantee their
accuracy, and all materials are provided without any warranty whatsoever, including, but not limited to, the implied warranties of
merchantability or fitness for a particular purpose. The name used in the data files for this course is that of a fictitious company. Any
resemblance to current or future companies is purely coincidental. We do not believe we have used anyone's name in creating this
e
course, but if we have, please notify us and we will change the name in the next revision of the course. Logical Operations is an
independent provider of integrated training solutions for individuals, businesses, educational institutions, and government agencies.
at

The use of screenshots, photographs of another entity's products, or another entity's product name or service in this book is for
editorial purposes only. No such use should be construed to imply sponsorship or endorsement of the book by nor any affiliation of
such entity with Logical Operations. This courseware may contain links to sites on the Internet that are owned and operated by third
lic

parties (the "External Sites"). Logical Operations is not responsible for the availability of, or the content located on or through, any
External Site. Please contact Logical Operations if you have any concerns regarding such links or External Sites.
up

TRADEMARK NOTICES
Logical Operations and the Logical Operations logo are trademarks of Logical Operations, Inc. and its affiliates.
®
Python is a registered trademark of the Python Software Foundation (PSF) in the U.S. and other countries. All other product and
service names used may be common law or registered trademarks of their respective proprietors.
D

Copyright © 2017 Logical Operations, Inc. All rights reserved. Screenshots used for illustrative purposes are the property of the
software proprietor. This publication, or any part thereof, may not be reproduced or transmitted in any form or by any means,
electronic or mechanical, including photocopying, recording, storage in an information retrieval system, or otherwise, without
ot

express written permission of Logical Operations, 3535 Winton Place, Rochester, NY 14623, 1-800-456-4677 in the United States
and Canada, 1-585-350-7000 in all other countries. Logical Operations’ World Wide Web site is located at
www.logicaloperations.com.
N

This book conveys no rights in the software or other products about which it was written; all use or licensing of such software or
other products is the responsibility of the user according to terms and conditions of the owner. Do not make illegal copies of books
or software. If you believe that this book, related materials, or any other Logical Operations materials are being reproduced or
transmitted without permission, please call 1-800-456-4677 in the United States and Canada, 1-585-350-7000 in all other countries.
o
D
Python® Programming:
Advanced

e
ut
ib
tr
is
Lesson 1: Using Object-Oriented Python.........................1

D
Topic A: Create and Use Classes in an Application..........................2
Topic B: Use Magic Methods......................................................... 15

or
Topic C: Incorporate Class Factories............................................. 25
e
Lesson 2: Creating a GUI...............................................33
at

Topic A: Design a GUI...................................................................34


lic

Topic B: Create and Arrange a GUI Layout.....................................38


Topic C: Interact with User Events................................................ 47
up

Lesson 3: Using Databases........................................... 59


D

Topic A: Basics of Data Management............................................ 60


ot

Topic B: Use SQLite Databases......................................................64


Topic C: Manipulate SQL Data.......................................................75
N

Lesson 4: Network Programming.................................. 85


o
D

Topic A: Basics of Network Programming..................................... 86


Topic B: Create a Client/Server Program....................................... 89
| Python® Programming: Advanced |

Lesson 5: Managing Multiple Processes with Threading...... 103


Topic A: Create a Threaded Application................................................ 104
Topic B: Manage Thread Resources...................................................... 112

e
Lesson 6: Implementing Unit Testing.................................. 125

ut
Topic A: Test-Driven Development....................................................... 126

ib
Topic B: Write and Run a Unit Test Case............................................... 130
Topic C: Create a Test Suite..................................................................136

tr
is
Lesson 7: Packaging an Application for Distribution........... 143

D
Topic A: Create a Package Structure..................................................... 144
Topic B: Generate the Package Distribution Files.................................. 151

or
Topic C: Generate a Windows Executable..............................................156

Solutions............................................................................................ 165
e
Glossary............................................................................................. 169
at

Index.................................................................................................. 173
lic
up
D
ot
N
o
D
About This Course

e
ut
ib
Python® continues to be a popular programming language, perhaps owing to its ability to
get a lot of work done in few lines of code, and its versatility. Python is useful for

tr
developing custom software tools, applications, web services, and cloud applications. In this
course, you'll build upon your basic Python skills, learning more advanced topics such as

is
object-oriented programming patterns, development of graphical user interfaces, data
management, threading, unit testing, and creating and installing packages and executable

D
applications.

Course Description
Target Student or
This course is designed for existing Python programmers who have at least one year of
e
Python experience and who want to expand their Python proficiencies.
at

Course Prerequisites
To ensure your success in this course, you should have experience with object-oriented
lic

programming and Python 2.x or 3.x. You can obtain this level of skill and knowledge by
taking the following Logical Operations course:
• Python® Programming: Introduction
up

Course Objectives
In this course, you will expand your Python proficiencies.
D

You will:
• Create object-oriented Python applications.
• Design and create a GUI.
ot

• Store data in a database from Python applications.


• Communicate using client/server network protocols.
N

• Manage multiple processes with threading.


• Implement unit testing.
• Package an application for distribution.
o

The CHOICE Home Screen


D

Logon and access information for your CHOICE environment will be provided with your
class experience. The CHOICE platform is your entry point to the CHOICE learning
experience, of which this course manual is only one part.
| Python® Programming: Advanced |

On the CHOICE Home screen, you can access the CHOICE Course screens for your specific
courses. Visit the CHOICE Course screen both during and after class to make use of the world of
support and instructional resources that make up the CHOICE experience.
Each CHOICE Course screen will give you access to the following resources:
• Classroom: A link to your training provider's classroom environment.
• eBook: An interactive electronic version of the printed book for your course.
• Files: Any course files available to download.
• Checklists: Step-by-step procedures and general guidelines you can use as a reference during

e
and after class.

ut
• Spotlights: Brief animated videos that enhance and extend the classroom learning experience.
• Assessment: A course assessment for your self-assessment of the course content.
• Social media resources that enable you to collaborate with others in the learning community

ib
using professional communications sites such as LinkedIn or microblogging tools such as
Twitter.

tr
Depending on the nature of your course and the components chosen by your learning provider, the
CHOICE Course screen may also include access to elements such as:

is
• LogicalLABS, a virtual technical environment for your course.
• Various partner resources related to the courseware.

D
• Related certifications or credentials.
• A link to your training provider's website.
• Notices from the CHOICE administrator.

• Mentoring services. or
• Newsletters and other communications from your learning provider.

Visit your CHOICE Home screen often to connect, communicate, and extend your learning
e
experience!
at

How to Use This Book


lic

As You Learn
This book is divided into lessons and topics, covering a subject or a set of related subjects. In most
cases, lessons are arranged in order of increasing proficiency.
up

The results-oriented topics include relevant and supporting information you need to master the
content. Each topic has various types of activities designed to enable you to solidify your
understanding of the informational material presented in the course. Information is provided for
D

reference and reflection to facilitate understanding and practice.


Data files for various activities as well as other supporting files for the course are available by
download from the CHOICE Course screen. In addition to sample data for the course exercises, the
ot

course files may contain media components to enhance your learning and additional reference
materials for use both during and after the course.
N

Checklists of procedures and guidelines can be used during class and as after-class references when
you're back on the job and need to refresh your understanding.
At the back of the book, you will find a glossary of the definitions of the terms and concepts used
o

throughout the course. You will also find an index to assist in locating information within the
instructional components of the book.
D

As You Review
Any method of instruction is only as effective as the time and effort you, the student, are willing to
invest in it. In addition, some of the information that you learn in class may not be important to you
immediately, but it may become important later. For this reason, we encourage you to spend some
time reviewing the content of the course after your time in the classroom.

| About This Course |


| Python® Programming: Advanced |

As a Reference
The organization and layout of this book make it an easy-to-use resource for future reference.
Taking advantage of the glossary, index, and table of contents, you can use this book as a first
source of definitions, background information, and summaries.

Course Icons
Watch throughout the material for the following visual cues.

e
Icon Description

ut
A Note provides additional information, guidance, or hints about a topic or task.

A Caution note makes you aware of places where you need to be particularly careful

ib
with your actions, settings, or decisions so that you can be sure to get the desired
results of an activity or task.

tr
Spotlight notes show you where an associated Spotlight is particularly relevant to
the content. Access Spotlights from your CHOICE Course screen.

is
Checklists provide job aids you can use after class as a reference to perform skills
back on the job. Access checklists from your CHOICE Course screen.

D
Social notes remind you to check your CHOICE Course screen for opportunities to
interact with the CHOICE community using social media.

or
e
at
lic
up
D
ot
N
o
D

| About This Course |


D
o
N
ot
D
up
lic
at
e
or
D
is
tr
ib
ut
e
1 Using Object-Oriented
Python

e
ut
Lesson Time: 3 hours, 45 minutes

ib
tr
is
Lesson Objectives

D
In this lesson, you will:

• Use magic methods for Python classes.or


• Define the components of an object-oriented Python program.

• Use class factories to create classes.


e
at

Lesson Introduction
lic

Advanced Python® applications are often developed using object-oriented programming


techniques, which make it easier to share code between applications. By reusing code, you
can cut down on your program development time, as well as maintain consistency between
up

your applications. Python provides support for most standard object-oriented programming
features to enable you to build complete object-oriented applications.
D
ot
N
o
D
2 | Python® Programming: Advanced

TOPIC A
Create and Use Classes in an Application
Object-oriented programming enables you to organize and reuse common features in applications.
In this topic, you’ll create and use classes.

e
You may want show the
Spotlight presentations Note: To learn more, view the Spotlight presentations from the Spotlight tile on the CHOICE

ut
from the CHOICE course screen.
Course screen or have
students navigate out to

ib
the Course screen and Classes
watch them as a
supplement to your With object-oriented programming, everything is related to classes. Classes are the data and functions

tr
instruction. If not, please you use in your applications, grouped together into a single entity. For example, if you’re writing a
remind students to visit program that uses cars, you can create a car class that contains information on the car’s make,
the Spotlights for this

is
model, price, and how many doors it has. If you’re writing an application that tracks people, you
course on their CHOICE
Course screen after might create a person class that contains information on each person’s name, age, height, weight,
and gender. An object-oriented programming class defines an object using members. There are two

D
class for supplemental
information and basic types of class members:
additional resources. • Attributes—denote features of an object (such as the weight, engine, and number of doors of a
Classes

or
car). A class can contain many attributes, each describing a different feature of the car.
• Methods—similar to Python functions, perform an operation using the attributes of the class. A
class method should be contained within the class and only use the attributes from that class.
You define the attributes and methods inside a class definition. The class definition uses the class
e
keyword, along with the class name. While not required, it's become somewhat standard in Python
at

for class names to begin with an uppercase letter. Follow the class name with a colon to indicate
more code is required to define the class:
lic

>>> class Car:


...
>>>
up

After defining the class, you can use it anywhere in your program to denote that object. Each use of
the class is called an instance. Each class instance is assigned to a variable in the program:
>>> car1 = Car()
>>>
D

The car1 variable is an instance of the Car class.


ot

Attributes
Attributes Attributes are variables that hold data that applies to the class. There are two types of attributes you
N

can define in Python:


• Class attributes—apply to all instances of the class.
Consider discussing with
o

• Instance attributes—apply only to a specific instance of the class.


students various ways
one might take You define class attributes as part of the class definition:
D

advantage of the ability >>> class Car:


to add attributes to an ... axles = 2
object on the fly, and ... wheels = 4
whether they would
...
consider that a good or
bad practice, based on Instance attributes only apply to a specific instance of the class. Python allows you to create instance
object-oriented attributes "on the fly" after the class instance has been created:
programming principles.

Lesson 1: Using Object-Oriented Python | Topic A


Python® Programming: Advanced | 3

>>> car1 = Car()


>>> car1.make = "Chevy"
>>>
The make attribute shown here only applies to the car1 instance of the Car class.

Methods
Classes consist of more than just a bunch of attributes. You also need to bundle functions for Methods

e
handling the attributes. In object-oriented programming, functions are called methods. Just like with
attributes, there are two types of methods that you can define in Python:

ut
• Class methods
• Instance methods

ib
Class Methods

tr
Class methods are functions that are independent of any instance data. To define a class method, Class Methods
you must first add an @classmethod decorator line before the method definition. You then define

is
the method much like a function, including the def keyword:
>>>class Car:

D
... @classmethod
... def calcMPG(cls, miles, gallons):
... return miles / gallons
...
or
The class method uses parameters to pass data into the method, and the return statement to pass a
single value back to the main program. The first parameter must be the cls keyword. This tells
e
Python to reference the class instead of an instance of the class.
at

The calcMPG class method uses the variables passed to it in the arguments, and returns the output
back to the main program
lic

Instance Methods
Instance methods work on attributes defined for the instance. Instance methods must always use at Instance Methods
up

least one parameter, called self. The self parameter points to the instance that's using the method.
When you use the instance method, you don't include the self parameter, Python assumes it by
default.
D

To define an instance method again, you use the def keyword, just like when defining functions:
>>>class Car:
... def __init__(self, make, model, price, inventory):
ot

... self.make = make


... self.model = model
... self.price = price
N

... self.inventory = inventory


... def display(self):
... print({0} {1} - price: {2:.2f}, inventory: {3:d}'.format(self.make,
o

self.model,
D

self.price,

self.inventory))
...
The __init__ instance method is a special method that defines the initial values for the instance
attributes. This will be discussed more later. The display method is an instance method created to

Lesson 1: Using Object-Oriented Python | Topic A


4 | Python® Programming: Advanced

display the instance values instead of having to use the print statement all the time when you want
to see the attribute values.
Inside the instance method definitions, the self keyword is used to reference the attribute values
for the instance. The __init__ method uses that to apply the parameter values to the instance
attributes. The display method also uses that in the self keyword to reference the values of the
attributes for the current instance.

Guidelines for Creating a Class

e
Define a Class

ut
Note: All Guidelines for this lesson are available as checklists from the Checklist tile on the
CHOICE Course screen.

ib
Students can enter the You create a complete class definition by putting together the class definition, attributes, and
example code using the methods into one code block.
Command Prompt

tr
feature in PyCharm to Define a Class
see the results as you
Define a new class by using the class keyword, along with the class name and a colon. The class

is
go through the sections.
name you choose must be unique within your program. Although it’s not required, it’s somewhat of
a de facto standard in Python to start class names with an uppercase letter:

D
>>> class Car:
...

Define a Class Attribute


Define a Class Attribute
or
After creating the class, you can define any class attributes. The class attributes apply to all instances
of the class. You reference the class attributes directly from the class and not from an instance:
e
... wheels = 4
at

... axles = 2
...
lic

Define a Class Method


Define a Class Method
Class methods are defined to provide methods for use outside of class instances, such as common
up

functions that can be used with the object. Remember to use the @classmethod decorator before
defining the class method, and use the cls keyword as the first parameter:
... @classmethod
... def calcMPG(cls, miles, gallons):
D

... return miles / gallons


...
ot

Note: Be careful when defining methods in a class definition. Make sure that the method code
block is indented farther than the method definition statement.
N

Define an Instance
Method Define an Instance Method
Define instance methods that support the class object. Use the __init__ method to create a class
o

constructor to define any instance variables for the class. Then create additional instance methods to
support functions required to interact with the class objects:
D

... def __init__(self, make, model, price, inventory):


... self.make = make
... self.model = model
... self.price = price
... self.inventory = inventory
... def sellCar(self, quantity):

Lesson 1: Using Object-Oriented Python | Topic A


Python® Programming: Advanced | 5

... self.inventory = self.inventory - quantity


...
>>>

Create an Instance
Create an Instance
The class definition creates the class template, but doesn’t put the class to use. To use a class, you
have to instantiate it. When you instantiate a class, you create an instance of the class in your
program. Each instance represents one occurrence of the object. Each instance is a separate object

e
in Python. If you create a second instance of the Car class, the attributes you define are separate
from the attributes you define in the first instance:

ut
>>> car1 = Car("Chevy", "Volt", 15000.00, 10)
>>> car1.make

ib
Chevy
>>>car2 = Car("Ford", "Focus", 10000.00, 5)
>>> car2.make

tr
Ford
>>> car1.make

is
Chevy
>>> Car.wheels
4

D
>>>Car.calcMPG(120, 3.3)
36.36363636363637
>>>>>>car1.sellCar(3)
>>>car1.inventory
7
>>>
or
e
Properties
at

Unlike many other programming languages, Python classes are dynamic. That means any program Properties
lic

using the class can add, delete, or modify instance attributes on the fly. That can be somewhat Point out that properties
dangerous, as you lose control over just how the class you created is being used. provide more control
over class attributes.
To regain control over the attributes, Python provides properties. A property is a protected attribute
up

that can only be modified by using special instance methods called setters and retrieved by using
special class methods called getters.
To identify a property, start the attribute name with two underscores:
D

... self.__make = make


... self.__model = model
... self.__price = price
ot

... self.__inventory = inventory


You must define getters and setters for each property. The getters start with get_ and the setters Define Setters and
start with set_, like this: Getters
N

>>>class Car:
... def __init__(self, make):
o

... self.__make = make


... def get_make(self):
D

... return self.__make


... def set_make(self, make):
... self.__make = make
...
>>>
This example is quite simple, but now that you have methods that intervene when you set or get Discuss various kinds of
tasks one might perform
data values, you can use those methods to perform certain checks or perform other tasks when the
in setters and getters.

Lesson 1: Using Object-Oriented Python | Topic A


6 | Python® Programming: Advanced

data values are being changed. For example, in the setter, you could write code to make sure the data
value is in a valid format or within an appropriate range. You might trigger changes in other
attributes, too.
The Property Method The downside to using getters and setters is that now you need to remember and use separate
methods for each property and function that you need to use in your program. For programs with
lots of properties, that can be a lot of methods to use! To solve that problem, Python uses the
property method. With the property method, you define the getter, setter, and an optional deleter
method for the property:

e
... make = property(get_make, set_make, del_make)
You still need to define all of the getter, setter, and deleter methods in your class code, but at least

ut
now using them is much easier. The program can reference the property with just the property
name:

ib
>>> car1.make = "Chevy"
Python calls the appropriate getter or setter method to accomplish the function.

tr
Guidelines for Creating a Property

is
When you create one or more properties for a class, you must also create the getters and setters for
each property.

D
Create a Property
Create a Property

>>>class Car:
...
or
Use two underscores in front of each attribute name that you want to become a property:

def __init__(self, make, model, price, inventory):


e
... self.__make = make
... self.__model = model
at

... self.__price = price


... self.__inventory = inventory
...
lic

Create a Getter Method


Create a Getter Method
up

When you create properties, create a getter method for each property. The getter method just
returns the value of the property to the calling program:
... def get_make(self):
D

... return self.__make


... def get_model:
... return self.__model
ot

... def get_price:


... return self.__price
... def get_inventory:
N

... return self.__inventory

Create a Setter Method


Create a Setter Method
o

For each property, create a setter method so that programs that use the class can change the value of
D

the property:
... def set_make(self, make):
... self.__make = make
... def set_model(self, model):
... self.__model = model
... def set_price(self, price):
... self.__price = price

Lesson 1: Using Object-Oriented Python | Topic A


Python® Programming: Advanced | 7

... def set_inventory(self, inventory):


... self.__inventory = inventory

Define a Property()
Define a Property() Method Method
After you define the getters and setters, you can combine them in property methods:
... make = property(get_make, set_make)
... model = property(get_model, set_model)
... price = property(get_price, set_price)

e
... inventory = property(get_inventory, set_inventory)

ut
Use the Property in an
Use the Property in an Instance Instance
To reference the class properties, don't use the underscores in the attribute, but instead use the

ib
property names:
>>>car1 = Car("Chevy", "Volt", 15000.00, 10)

tr
>>> car1.make
'Chevy'

is
>>> car1.make = "Ford"
>>> car1.make
'Ford'

D
>>>

Inheritance
or
When creating classes, you want to keep the class definition as generic as possible so that it can fit as
many application environments as possible. However, often you need to build onto a class definition
Inheritance
e
to fit a specific application environment.
at

Python allows you to do that with inheritance. Inheritance allows you to create a subclass from a main
class (called the superclass). A subclass contains (inherits) all of the original attributes and methods of
the superclass, plus adds its own attributes and methods specific to the subclass.
lic

To create a subclass, you must reference the superclass that it inherits when you define it:
>>> class Sedan(Car):
up

When you create the subclass, Python doesn't automatically call the constructor for the superclass,
so you must reference it in the constructor for the subclass:
>>>class Car:
D

... def __init__(self, make, model):


... self.make = make
... self.model = model
ot

...
>>>class Sedan(Car):
... def __init__(self, make, model, doors, seats):
N

... super(Sedan, self).__init__(make, model)


... self.doors = doors
... self.seats = seats
o

...
>>>
D

The constructor for the Sedan subclass uses the super method to inherit the attributes and
methods of the superclass. This calls the __init__ method for the Car superclass, passing the
constructor values to the superclass.
The subclass can define its own methods, but it can also define the same methods as the superclass.
This is called overloading the method. If the same method is defined in both the superclass and the
subclass, objects created using the subclass use the overloaded method from the subclass, while
objects created using the superclass use the methods from the superclass.

Lesson 1: Using Object-Oriented Python | Topic A


8 | Python® Programming: Advanced

Guidelines for Using Inheritance


Here are some guidelines you should follow when using inheritance to create a subclass.
Use the Super Method
Use the Super Method
Make sure that you use the super method to pass any constructor values to the superclass. In the
following example, notice that Car is specified as the superclass in the definition for the Sedan class.
So super(Sedan, self).__init__ refers to the constructor for the Car class:

e
>>>class Car:

ut
... def __init__(self, make, model, price, inventory):
... self.make = make
... self.model = model

ib
... self.price = price
... self.inventory = inventory
... def display(self):

tr
... print('{0} {1}'.format(self.make, self.model))
...

is
>>>class Sedan(Car):
... def __init__(self, make, model, price, inventory, doors, seats):
... super(Sedan, self).__init__(make, model, price, inventory)

D
... self.doors = doors
... self.seats = seats
...

Overload Any Required


Methods Overload Any Required Methods or
Define any overload methods that need to supersede the superclass methods:
e
... def display(self):
at

... print('{0} {1} is a sedan with {2} doors and {3}


seats'.format(self.make, self.model, self.doors, self.seats))
>>>
lic

Use the Subclass to


Instantiate New Objects Use the Subclass to Instantiate New Objects
up

Use the subclass name to instantiate new objects instead of the superclass name. Use the superclass
name to instantiate any objects that don't use the subclass, but instead use the superclass. Remember
that overloaded methods will behave differently for the subclass and superclass instances:
>>> sedan1 = Sedan("Ford", "Focus", 10000.00, 5, 4, 5)
D

>>> car1 = Car("Chevy", "Volt", 15000.00, 10)


>>> sedan1.doors
4
ot

>>> sedan1.display()
Ford Focus is a sedan with 4 doors and 5 seats
N

>>>car1.display()
Chevy Volt
>>>
o

Guidelines for Using Object-Oriented Classes in Python


D

Guidelines for Using Use the following guidelines to help when working with classes in your Python programs:
Object-Oriented Classes • Use classes to combine data and functions that are related.
in Python
• Define the class using the class statement.
• Define a constructor for the class using the __init__() method.
• Use class attributes for sharing values between instances.

Lesson 1: Using Object-Oriented Python | Topic A


Python® Programming: Advanced | 9

• Use instance attributes for creating attributes unique to each instance.


• Define properties for the class by creating getters, setters, and deleters for any attributes you
want to define.
• Define additional methods as needed for manipulating class properties.
• Create an instance of the class by using the format variable = Class(args).
• Reference any class properties from the instance using the format variable.property.
• Reference any class methods from the instance using the format variable.method().
• Keep object classes as generic as possible. Use inheritance to create customized objects from

e
parent objects.
• Create classes and subclasses in modules so that you can easily use them in your Python

ut
programs.

ib
tr
is
D
or
e
at
lic
up
D
ot
N
o
D

Lesson 1: Using Object-Oriented Python | Topic A


10 | Python® Programming: Advanced

ACTIVITY 1-1
Creating an Object-Oriented Class

Before You Begin

e
Ensure that Python version 3.4.2 and the PyCharm Community Edition IDE version 3.4.1 are

ut
installed on your computer.

Scenario

ib
You are developing Python applications that will be used by a local car dealer. You have been tasked
to create an application that maintains records of the vehicles in inventory. As you use object-
oriented programming classes in your Python applications, you'll want to save them in separate

tr
module files. Using PyCharm, you'll create a new project to build a module for handling the Car and
Sedan classes. You can then use that module in any Python application that requires those classes.

is
Activity: Creating an
Object-Oriented Class Note: Activities may vary slightly if the software vendor has issued digital updates. Your

D
Notify students of any instructor will notify you of any changes.
changes to activities
based on digital software
updates issued by the
software vendor.
1. Open PyCharm and create a new project.
or
a) From the desktop, double-click the JetBrains PyCharm Community Edition 3.4 shortcut.
b) In the PyCharm Community Edition window, select Create New Project.
e
Note: If you already have a project open, select File→Close Project from the
at

menu bar to open the PyCharm Community Edition window, then select
Create New Project.
c) In the Create New Project dialog box, in the Project name text box, type AdvPython
lic

d) Next to the Location field, select the Browse button to open the Select Location for Project Directory
dialog box.
e) In the top-left corner of the Select Location for Project Directory dialog box, select the Home
up

Directory button to select your user directory.


f) Under your user name, select the triangle next to the Desktop directory to show subdirectories
beneath it.
D

g) Beneath the Desktop directory, select the triangle next to the AdvPython directory to show
subdirectories beneath it.
h) Select the Using Object-Oriented Python directory, and select OK.
ot

Note: If you receive a message from Windows Firewall, select Allow Access. If
the Tip of the Day dialog box is shown, close it.
N

i) Select OK again to create the project.


j) Verify that AdvPython is listed in the Project window on the left side of the PyCharm window.
o

2. Create the class module file.


D

a) Right-click AdvPython and select New→Python File.


b) In the Name text box, enter cars
c) Select the OK button.

3. Type the code to create the Car class.

Lesson 1: Using Object-Oriented Python | Topic A


Python® Programming: Advanced | 11

a) Enter the class definition statement, and define the constructor by adding the following code. If you would prefer that
you or your students not
type the code in step 3,
you can copy it from
SNIPPET 1, provided in
Snippets.txt.

e
ut
ib
b) Enter the setter and getter methods by adding the following code after the constructor.

tr
is
D
or
e
at
lic
up

Note: Alignment matters in Python. Please make sure your code is indented
as shown here.
D

c) Enter the property definitions for each attribute of the Car class by typing the following after the
getter and setter methods.
ot
N
o
D

Lesson 1: Using Object-Oriented Python | Topic A


12 | Python® Programming: Advanced

d) Enter the display() and sellCar() methods by typing the following after the property
definitions.

e
ut
ib
4. Type the code to create the Sedan subclass in the cars.py file.
If you would prefer that a) After the Car class code, enter the code to create the Sedan subclass by typing the following.

tr
you or your students not
type the code in step 4,

is
you can copy it from
SNIPPET 1, provided in
Snippets.txt.

D
or
e
at
lic
up
D
ot
N
o
D

Lesson 1: Using Object-Oriented Python | Topic A


Python® Programming: Advanced | 13

ACTIVITY 1-2
Using an Object-Oriented Class in an
Application

e
Before You Begin

ut
You have created the AdvPython project and the cars.py file. The AdvPython project is open in
PyCharm.

ib
Activity: Using an
Scenario Object-Oriented Class in
an Application

tr
Before you start writing the full application, you want to test out the Car and Sedan classes that you
previously built. You will create a new module to test creation and use of the new classes.

is
1. Create the cartest.py test file in the AdvPython project.

D
a) Right-click the AdvPython project in the PyCharm window.
b) Select New→Python File.
c) In the Name text box, enter the file name cartest
d) Select the OK button.

2. Write code to create an instance of each class.


or
e
a) Type the following to import the Car and Sedan class definitions from the car.py file.
at
lic
up

b) Type the following to create an instance of both the Car and Sedan classes.
If you would prefer that
you or your students not
D

type the code in step 2b,


you can copy it from
SNIPPET 2, provided in
ot

Snippets.txt.

3. Enter code to perform some basic tests of the Car and Sedan classes.
N

a) Display both the Car and Sedan instance values using the display() method by typing the If you would prefer that
following. you or your students not
o

type the code in the step


3 sub-steps, you can
D

copy it from SNIPPET 3,


provided in Snippets.txt.

Lesson 1: Using Object-Oriented Python | Topic A


14 | Python® Programming: Advanced

b) Simulate selling three cars by using the sellCar() method, then display the results by typing the
following.

c) Simulate changing the sedan information by changing the number of doors to 3. Do that by typing

e
the following.

ut
ib
tr
4. Run the cartest.py program to test it.

is
a) Select Run→Run.

D
or
e
b) In the pop-up window, select cartest.
c) Examine the output.
at
lic
up
D
ot

The first two lines show the car1 and sedan1 instance values that you defined. The third line
shows the result of the sellCar(3) method that you ran, and the fourth line shows the result of
N

changing the doors property of the sedan to 3.


o
D

Lesson 1: Using Object-Oriented Python | Topic A


Python® Programming: Advanced | 15

TOPIC B
Use Magic Methods
Python provides a host of built-in methods that you can use with any class objects that you create.
These methods are often called magic methods, special methods, or helper methods. In this topic,
you'll explore what built-in magic methods are available, and how to use them in your programs.

e
ut
Constructor and Destructor Methods
The __init__ constructor method provides a way for an application to define initial values for Constructor and

ib
attributes when you instantiate it. The default format for a constructor method lists the attribute Destructor Methods
values as parameters, then assigns the parameter values to the attributes: Remind students of the

tr
>>> class Car: __init__ method
... def __init__(self, make, model, price, inventory): described in Topic A,
and explain that it is a

is
... self.make = make
constructor method.
... self.model = model
... self.price = price

D
... self.inventory = inventory
...
>>>

or
However, having to provide values for each parameter can be somewhat painful, especially if there
are any values that are often the same, such as the number of doors or seats on a sedan object. To
prevent having to enter common values, you can define default values inside the constructor
e
definition:
at

>>> class Sedan(Car):


... def __init__(self, make, model, price, inventory, doors = 4, seats = 5):
... Car.__init__(self, make, model, price, inventory)
lic

... self.doors = doors


... self.seats = seats
...
up

>>>
Another magic method that comes in handy is the destructor. The destructor method runs when you
delete an instance of the class. This allows you to perform some clean-up functions before the
instance goes away. This is especially handy if you have an application that opens lots of files. It's a
D

good idea to make sure all of the files are closed before the instance goes away.
The destructor uses the __del__ method:
ot

... def __del__(self):


...
The code that you define in the destructor only runs when a class instance is removed from memory
N

by Python as the program runs. You can manually delete a class instance at any time using the del
statement.
o

Note: Python will attempt to automatically remove unused class instances from memory when it
detects they are no longer in use in an application. However, for large applications that use a lot
D

of memory, it can be beneficial to manually delete the instance yourself to help increase
performance.

Lesson 1: Using Object-Oriented Python | Topic B


16 | Python® Programming: Advanced

Guidelines for Defining Constructors


Use constructors when you need to define values for class attributes, or set default values for class
attributes.
Using a Constructor
Using a Constructor
When you define a constructor, the instance must provide a value for each parameter defined in the
constructor. If you don't provide enough parameters, you'll get an error message from Python:

e
>>> class Car:

ut
... def __init__(self, make, model, price, inventory):
... self.make = make
... self.model = model

ib
... self.price = price
... self.inventory = inventory
...

tr
>>> car1 = Car("Chevy", "Volt", 15000.00)
Traceback (most recent call last):

is
File "<input>", line 1, in <module>
TypeError: __init__() missing 1 required positional argument: 'inventory'
>>>

D
Defining Default
Attribute Values Defining Default Attribute Values
Point out that initializing
all instance attributes in
the constructor also
enables you to write
programmatic checks to
or
If you don't want to have to define values for all of the attributes, define default attribute values in
the constructor. Then, any missing parameters are assumed to take their default values. A good
practice is to initialize all instance attributes in the constructor, even if they only create placeholders.
That will prevent exceptions for situations when an attribute doesn't exist:
e
examine attributes once >>> class Sedan(Car):
at

the object is created. ... def __init__(self, make, model, price, inventory, doors = 4, seats = 5):
... Car.__init__(self, make, model, price, inventory)
... self.doors = doors
lic

... self.seats = seats


...
>>> sedan1 = Sedan("Chevy", "Volt", 15000.00, 10)
up

>>>sedan1.display()
This sedan has 4 doors and 5 seats
>>>
D

Guidelines for Using Constructors and Destructors


ot

Guidelines for Using Use the following guidelines when deciding when to create constructors or destructors in your
Constructors and Python classes:
Destructors
• Create a constructor when you need to initialize attributes or properties in your classes.
N

• Define commonly used attribute values in a constructor.


• Create a destructor if you need to perform housekeeping functions on a class before it deletes,
such as closing files.
o

• Use the del statement to remove a class object from memory when it's no longer needed in an
D

Point out that since application.


Python treats everything
as an object, you can
define how any objects Comparison Methods
used in programs are
compared to one It's common programming practice to use if-then statements in Python code to perform
another for equality. comparisons between two values, such as to compare two variables that hold integers, or two
Comparison Methods

Lesson 1: Using Object-Oriented Python | Topic B


Python® Programming: Advanced | 17

strings. Sometimes, it also comes in handy to be able to compare two objects, as well, but that can
get somewhat tricky.
Just how do you compare two Car class instances? There can be many attributes assigned to a class,
so it would be impossible for Python to know just which ones to compare:
>>> car1 = Car("Chevy", "Volt", 15000.00, 10)
>>> car2 = Car("Ford", "Focus", 10000.00, 20)
>>> if (car1 > car2):
... print("The Volt is bigger")

e
...
Traceback (most recent call last):

ut
File "<input>", line 1, in <module>
TypeError: unorderable types: Car() > Car()
>>>

ib
Python has no way to determine what the greater-than operation means when working with the Car
class objects. However, Python does provide a way for us to tell it just what to do. This is called a

tr
comparison method:
... def __gt__(self, other):

is
... if (self.price > other.price):
... return True

D
This code uses the price attribute of the Car class to determine if one Car object is greater than
another. Since it is a method, it returns a True boolean value if the condition is true. The magic part
of this method is that not only can you now use the __gt__ method for the class, you can also use
the actual greater-than symbol ( > ) to compare Car objects.

when you need to use them in comparisons.


or
Python provides a whole host of comparison magic methods that you can define in your classes List of Comparison
Methods
e
Comparison Method Description
at

__eq__ Equal
__ge__ Greater-than or equal
lic

__gt__ Greater-than
__le__ Less-than or equal
up

__lt__ Less-than
__ne__ Not equal
D

You don't need to define all of the comparison methods in the class, only the ones you need to use
in your applications.
ot

Guidelines for Working with Comparison Methods


N

Comparison methods provide a way for you to define how your classes will behave when
comparison operations are performed on them.
o

Working with
Working with Comparison Methods Comparison Methods
D

Define comparison methods after the constructor. You don't need to define all of the comparison
methods, just the ones that you need to use for your class:
>>> class Car:
... def __init__(self, make, model, price, inventory):
... self.make = make
... self.model = model
... self.price = price

Lesson 1: Using Object-Oriented Python | Topic B


18 | Python® Programming: Advanced

... self.inventory = inventory


... def __gt__(self, other):
... if (self.price > other.price):
... return True
... def __lt__(self, other):
... if (self.price < self.other):
... return True
... def __eq__(self, other):
... if (self.price == self.other):

e
... return True

ut
...
>>> car1 = Car("Chevy", "Volt", 15000.00, 10)
>>> car2 = Car("Ford", "Focus", 10000.00, 3)

ib
>>> if (car1 > car2):
... print("The {0} is more expensive than the {1}".format(car1.model,
car2.model)

tr
...
The Volt is more expensive than the Focus

is
>>>
>>> car1.price = 10000.00
>>> if (car1 == car2):

D
... print("Both cars are the same price")
...
Both cars are the same price
>>>

Numeric Methods
or
e
Remind students of how Python also includes several numeric operation magic methods that can come in handy. Numeric
at

Python handles integer methods enable you to define how your classes will behave when basic mathematical operations,
values and floating-point such as addition, subtraction, multiplication, and division, are performed on them, as treating the
values for numbers.
lic

classes as though they were simple numbers. Numeric methods also support some advanced
Numeric Methods mathematical operations, such as raising values to a power, or shifting values left or right.
Obviously, not all classes need to support all of the numeric magic methods, but they're available to
up

use if you need them. For our Car class, say you want to be able to find out the price difference
between two cars. To do that, you first need to define the __sub__ method in your Car class:
... def __sub__(self, other):
... return self.price - other.price
D

...
Then, you can easily subtract one car from another, implying that it’s actually the price you want to
ot

subtract:
difference = car1 – car2
N

As you can guess, Python provides numeric magic methods for most of the common mathematical
operations you'll run into.
List of Numeric Methods
o

Numeric Method Description


D

__add__ Addition
__and__ Boolean AND
__div__ Division
__divmod__ Division modulo
__floordiv__ Returns the integer part of the division

Lesson 1: Using Object-Oriented Python | Topic B


Python® Programming: Advanced | 19

Numeric Method Description


__lshift__ Shifts the number left
__mod__ Modulo
__mul__ Multiplication
__or__ Boolean OR
__pow__ Raising to a power

e
__rshift__ Shifts the number right

ut
__sub__ Subtraction
__xor__ Boolean XOR

ib
Just as with the comparison methods, you don't need to define all of the numeric methods for your
classes, just the ones you think you'll need to use in your applications.

tr
is
Guidelines for Working with Numeric Methods
Numeric methods provide a way for you to define how your classes will behave when simple

D
mathematical operations are performed on them.
Working with Numeric
Working with Numeric Methods
or
Just as with comparison magic methods, you only need to define the numeric magic methods that
you think you'll need to use for the class objects. Just define them anywhere after the constructor
method:
Methods
e
>>> class Car:
at

... def __init__(self, make, model, price, inventory):


... self.make = make
... self.model = model
lic

... self.price = price


... self.inventory = inventory
... def __add__(self, other):
up

... return self.price + other.price


... def __sub__(self, other):
... return self.price - other.price
...
D

>>> car1 = Car("Chevy", "Volt", 15000.00, 10)


>>> car2 = Car("Ford", "Focus", 10000.00, 3)
ot

>>> car1 - car2


5000.0
>>>
N
o
D

Lesson 1: Using Object-Oriented Python | Topic B


20 | Python® Programming: Advanced

ACTIVITY 1-3
Creating a Class Constructor and Destructor

Before You Begin

e
You have created the AdvPython project with cars.py and cartest.py. The AdvPython project is

ut
open in PyCharm.
Activity: Creating a
Class Constructor and Scenario

ib
Destructor
You will now add a constructor to the Sedan class that assumes default values for the doors and
seats attributes in the constructor. You will also add a destructor method in the Sedan class that

tr
displays the final values of the sedan instance before it is deleted.

is
1. In cars.py, edit the Sedan constructor to add default values.
a) In cars.py, scroll down to the Sedan class definition area.

D
b) Modify the __init__ function to set the default value of the doors parameter to 4 and the seats
parameter to 5

or
e
at
lic

2. Define the destructor.


a) Under the __init__ constructor section, but before the get_doors() method, add a __del__
up

section that uses the print method to display the instance values of all the attributes.
D
ot
N
o
D

3. Test the new constructor and destructor in the Python Console.

Lesson 1: Using Object-Oriented Python | Topic B


Python® Programming: Advanced | 21

a) Select Tools→Run Python Console from the PyCharm menu bar. The Python Console window
should appear at the bottom of the PyCharm window.

e
ut
b) In the Python Console, import all of the classes from the cars.py module file by typing the following.

ib
tr
is
D
c) Create an instance of the Sedan class, but don't specify the number of doors or seats by typing the
following.

or
e
at
lic

d) Display the instance attributes by using the display() method.


up
D
ot

e) Use the del method to destroy the sedan1 instance you created.
N
o
D

A message is displayed by the destructor that you created.

Lesson 1: Using Object-Oriented Python | Topic B


22 | Python® Programming: Advanced

f) Try to display the sedan1 instance to verify that it no longer exists. You will get an error message
that looks like the following.

e
ut
4. Close the console.
a) Select the Close button to close the console.

ib
tr
is
D
or
e
at
lic
up
D
ot
N
o
D

Lesson 1: Using Object-Oriented Python | Topic B


Python® Programming: Advanced | 23

ACTIVITY 1-4
Working with Comparison and Numeric Magic
Methods

e
Before You Begin

ut
You have created the AdvPython project with cars.py and cartest.py. You have modified the
constructor and added a destructor to cars.py. The AdvPython project is open in PyCharm, and

ib
cars.py is open for editing.
Activity: Working with
Scenario Comparison and

tr
Numeric Magic Methods
You will add methods to the Car class that enable you to compare prices on cars. You will add a
check for greater-than, less-than, and equal to the class definition.

is
D
1. Edit the Car class to add the new methods.
a) Following the __init__ method definition, add new definitions for the __eq__, __gt__, and
__lt__ methods as shown.

or If you would prefer that


you or your students not
type the code in step 1,
you can copy it from
e
SNIPPET 4, provided in
Snippets.txt.
at
lic
up
D
ot
N
o

In each case, a Boolean True value is return if the condition is met.


D

2. Test the new methods using the Python Console.


a) Open a new Python Console window by selecting Tools→Run Python Console from the menu bar.

Lesson 1: Using Object-Oriented Python | Topic B


24 | Python® Programming: Advanced

b) Import the Car class from the cars.py module file by typing the following.

e
c) Create two instances of the Car class, one more expensive than the other.

ut
ib
tr
is
D
d) Check if both of the Car instances have the same price by using an if-then statement and a
print statement as shown.

or
e
at
lic

Note: You must press Enter twice after the second line to return to the >>>
prompt.
up

Since the car prices are not the same, the if-then statement fails, and the print statement is
skipped.
e) Test if the first car is more expensive than the second car by typing the following.
Remind students to
D

enter the third line to


return to the >>>
prompt.
ot
N
o
D

Lesson 1: Using Object-Oriented Python | Topic B


Python® Programming: Advanced | 25

TOPIC C
Incorporate Class Factories
Object-oriented programming is all about consistency. The more your class definitions use standard
formats and interfaces, the more useful they'll be to use in a wider variety of applications. One of
the standards that helps Python programmers share classes is class factories. The class factory can

e
help you define a standard for classes and subclasses that makes it easier to implement them in your

ut
Python applications.

Simple Class Factory

ib
In a large Python application that uses several classes and subclasses, it's easy to get lost in a sea of Simple Class Factory

tr
class definitions. Trying to remember just what subclasses belong to which classes can be confusing.
Fortunately, you can use an advanced object-oriented feature called class factories to help keep things
straight.

is
A simple class factory gathers all of the subclasses that belong to the same superclass together into a Point out that class
single class definition. The factory provides one-stop shopping to instantiate any of the subclasses factories are often used

D
from a single class method. While this may sound confusing, it actually can help keep your in web development
subclasses in order, and help you to easily find just the right subclass for your application. frameworks, like Flask
®
and Django .

or
The key to a class factory is the factory method that you define for the superclass object. The
factory method uses a single parameter—the name of the subclass that you want to instantiate.
Based on the parameter, the factory instantiates the requested subclass object. The code to
implement a simple class factory looks like the following:
e
class Car:
at

def factory(type):
class Sedan(Car):
def display(self):
lic

print("This car is a sedan")


class Sports(Car):
def display(self):
up

print("This car is a sports car")


if (type == "Sedan"):
return Sedan()
if (type == "Sports"):
D

return Sports()
With this approach, you can group all of the subclass definitions together in the factory class for
easy access to any subclass.
ot

Polymorphic Class Factory


N

Often, subclasses overload the same class methods, tweaking the methods so that they incorporate Polymorphic Class
the differences related to each subclass. Trying to keep track of all the overloaded methods for each Factory
o

subclass can be yet another object-oriented programming nightmare. It would be nice to be able to
call a single method in your programs to retrieve the information specific to the subclass that you're
D

working with.
The polymorphic class factory enables you to call a single method to instantiate any subclass from a
superclass. The polymorphic class factory references all of the overload methods in subclasses, and
uses the correct one based on the subclass that was instantiated. There's no need to worry about
using the correct method for the correct subclass. The polymorphic class factory does that for you.
Assume that you have two subclasses that overload the same method:

Lesson 1: Using Object-Oriented Python | Topic C


26 | Python® Programming: Advanced

class Sedan(Car):
def display(self):
print("This is a sedan")

class Sports(Car):
def display(self):
print("This is a sports car")
Both the Sedan and Sports subclasses define the display() method, and each one does
something different. You can now create a polymorphic class factory method that calls the

e
appropriate subclass display() method based on the subclass of the object being used:

ut
def displayCar(carType):
carType.display()

ib
Now you can create multiple objects of different subclasses and call the same displayCar()
method to run the display() method for any of the subclasses.

tr
Abstract Class Factories

is
Abstract Class Factories You may run into situations where the superclass used for an object isn't used to create any
—The Need instances; all of the object instances in the application are created using subclasses. Because of that,

D
there isn't any reason to create a detailed class definition for the superclass. Each subclass just
defines the attributes and methods that it needs:
>>> class Car:
...
...
pass

>>> class Sedan(Car):


... def display(self):
or
e
... print("This is a sedan")
at

...
>>> class Sports(Car):
... def displayCar(self):
lic

... print("This is a sports car")


...
>>>
up

Notice, though, that the two separate subclasses use different methods to display the object
information. Because of that, if you accidentally use the wrong method for a subclass, you'll get an
error message:
D

>>> car1.displayCar()
Traceback (most recent call last):
File "<input>", line 1, in <module>
ot

AttributeError: 'Sedan' object has no attribute 'displayCar'


>>>

Abstract Class Factories To avoid this situation, you can create an abstract class factory. The abstract class factory creates the
N

—The Solution superclass with abstract templates for any method that you want to use for subclasses. You don't use
any code here, other than to provide an error message to display if the method isn't overloaded by
the subclass:
o

class Car:
D

def displayCar():
print("Sorry, this method is not implemented")
def sellCar():
print("Sorry, this method is not implemented")
Each subclass definition must overload all of the methods defined in the abstract class factory. If
any methods aren't overloaded and a program attempts to use them, the superclass method takes
over and displays an error message.

Lesson 1: Using Object-Oriented Python | Topic C


Python® Programming: Advanced | 27

Guidelines for Implementing Class Factories


When implementing class factories in your applications, be careful which type you use, and how you
use it.

Simple Class Factory


With a simple class factory, you just need to call the factory method of the superclass with the
name of the subclass you want:

e
>>> car1 = Car.factory("Sedan")
>>> car1.display()

ut
This car is a sedan
>>>

ib
Polymorphic Class Factory
With polymorphic class factories, you can define the same method for different objects and Python

tr
will use the appropriate class method for each object:
>>> car1 = Sedan()

is
>>> car2 = Sports()
>>> displayCar(car1)

D
This is a sedan
>>> displayCar(car2)
This is a sports car
>>>

Abstract Class Factory or


With the abstract class factory, if you attempt to use a subclass method that hasn't been defined, the
e
superclass abstract class kicks in and handles the request:. Using this method, you can code in more
user-friendly error messages than what you'd get from Python:
at

>>> car1 = Sedan()


>>> car1.displayCar()
lic

Sorry, this method is not implemented


>>>
up

Guidelines for Using Class Factories


Use the following guidelines when creating classes to determine when you should use a class factory: Guidelines for Using
D

• Create a simple class factory when you have multiple subclasses and want to easily manage them Class Factories
from the superclass.
• When creating a simple class factory, create a factory method in the superclass.
ot

• When creating a simple class factory, create the subclasses inside the factory method.
• Ensure that the factory method creates the appropriate subclass object based on the parameter
N

passed to it.
• When creating a polymorphic class factory, create a separate method for each overloaded
method in the subclasses.
o

• Ensure the polymorphic method runs the appropriate subclass overload method based on the
parameter passed to it.
D

• When creating an abstract class factory, ensure you create method templates for all of the
overloaded methods used in subclasses.
• Ensure the superclass method templates produce some type of error message or signal if a
subclass doesn't overload the method.

Lesson 1: Using Object-Oriented Python | Topic C


28 | Python® Programming: Advanced

ACTIVITY 1-5
Creating a Class Factory

Before You Begin

e
The AdvPython project is open in PyCharm.

ut
Activity: Creating a
Class Factory Scenario
Create a simple class factory that can create a Sedan or Sports subclass object using a single factory

ib
method defined in the Car superclass. Don't worry about adding attributes or extra methods for this
exercise; focus on the factory method and how to allow it to create subclass objects.

tr
is
1. Create the carfactory.py file in the AdvPython project.
a) In the left window, right-click on the AdvPython project name.
b) From the menu, select New →Python file.

D
c) In the Name text box, type carfactory
d) Select the OK button to create the file.

2. Enter the code for the Car class.


or
a) At the top of the open carfactory.py file, type the class statement to start the Car class definition,
and the def statement to start the factory() method as shown.
e
If you would prefer that
you or your students not
at

type the code in the step


2 sub-steps, you can
copy it from SNIPPET 5,
lic

provided in Snippets.txt.
up

b) Under the factory() definition, type the code to create the Sedan subclass.
D
ot
N
o

This class contains a single method named display() that just displays some text indicating that
the method has been run, as shown.
D

Lesson 1: Using Object-Oriented Python | Topic C


Python® Programming: Advanced | 29

c) After the Sedan subclass definition, create the Sports subclass.

e
ut
ib
tr
This class also includes a single method named display() that just displays some text indicating
that the method has been run.

is
d) Finish the factory() method code by adding two if statements that test the type attribute and run
the appropriate subclass.

D
or
e
at
lic
up
D
ot
N
o
D

Lesson 1: Using Object-Oriented Python | Topic C


30 | Python® Programming: Advanced

ACTIVITY 1-6
Using Class Factories in an Application

Before You Begin

e
The AdvPython project is open in PyCharm. The carfactory.py file is open in an editing tab.

ut
Activity: Using Class
Factories in an Scenario
Application
You will write code that uses a class factory to generate a Sedan and a Sports subclass object, and

ib
you will use the display() method to test which object is which.

tr
1. Write code to instantiate and display two different classes of car.

is
a) In carfactory.py, skip a line after the end of the Car class definition, then write statements to create
a Sedan and Sports car, using the Car class' factory() method.

D
or
e
b) Skip a line and write statements to call the display method for each car.
at
lic
up

2. Run the carfactory.py program from the AdvPython project.


D

a) In the Project window, right-click carfactory.py and select Run 'carfactory'.


b) Observe the results shown in the console window.
ot
N
o
D

The sedan1 object displayed the message for a sedan, and the sports1 object displayed the
message for a sports car.

3. Clean up the workspace.


a) Right-click the tab for the carfactory console window, and select Close All.
All console windows are closed.

Lesson 1: Using Object-Oriented Python | Topic C


Python® Programming: Advanced | 31

b) Select File→Close Project.


The project is closed.
c) Close the PyCharm Community Edition window to exit PyCharm.

e
ut
ib
tr
is
D
or
e
at
lic
up
D
ot
N
o
D

Lesson 1: Using Object-Oriented Python | Topic C


32 | Python® Programming: Advanced

Summary
In this lesson, you used object-oriented programming to help organize data and functions in your
Python programs. Object-oriented classes and subclasses make it easier to reuse code that describes
common objects between programs without having to rewrite code. You also used built-in Python
magic methods in your class definitions to provide extended functionality to your own classes and
subclasses. Finally, you used class factories to help organize complex class objects in programs.

e
Encourage students to
use the social What type of objects would be best to use for creating classes?

ut
networking tools A: Answers will vary. Objects that you use in multiple applications are the best candidates for converting
provided on the CHOICE into classes. The more times you use an object in different applications, the more time you save by
Course screen to follow not having to retype the code to define attributes and methods required for the object. If you only use

ib
up with their peers after
an object in a single application, there's not much time or work savings to benefit from.
the course is completed
for further discussion How can a large corporation benefit from implementing object-oriented Python programming?

tr
and resources to support
continued learning. A: Answers will vary. Since the key to getting the most out of object-oriented programming is reuse, the
best way for a company to benefit from object-oriented programming is to encourage their entire

is
programming staff to share objects they create. As programmers create classes for applications, they
should store the class module file in a common location for others to use. A shared code library of

D
classes and subclasses can save lots of programming time for large applications.

Note: Check your CHOICE Course screen for opportunities to interact with your classmates,

or
peers, and the larger CHOICE online community about the topics covered in this course or
other topics you are interested in. From the Course screen you can also access available
resources for a more continuous learning experience.
e
at
lic
up
D
ot
N
o
D

Lesson 1: Using Object-Oriented Python |


2 Creating a GUI

e
Lesson Time: 3 hours, 15 minutes

ut
ib
tr
Lesson Objectives

is
In this lesson, you will:

D
• Define how graphical applications work.
• Create a graphical interface for an application.

or
• Create methods for handing user events and data in a graphical window.

Lesson Introduction
e
at

Often, when you hear the term "Python® scripting," the first thing that comes to mind is
boring command-line scripts. However, these days, just about every operating system
incorporates some type of graphical user interface (GUI) to enable users to input data and
lic

view results. You can leverage the graphical desktop environment with your Python scripts
to create a fancy, windows-oriented interface for your programs that will help give your
scripts a more professional look and feel.
up
D
ot
N
o
D
34 | Python® Programming: Advanced

TOPIC A
Design a GUI
You've created Python applications that run in a console window, but now you want to create
something a bit more sophisticated—an application that runs in a Windows®-style user interface,
complete with buttons, text boxes, check boxes, and so forth.

e
You may want show the

ut
Spotlight presentations Note: To learn more, view the Spotlight presentations from the Spotlight tile on the CHOICE
from the CHOICE course screen.
Course screen or have

ib
students navigate out to
the Course screen and GUI Libraries
watch them as a

tr
supplement to your A lot of people have worked hard to simplify graphical user interface (GUI) programming in the
instruction. If not, please Python environment. Standard library packages help you create GUI widgets from your Python

is
remind students to visit scripts and build your graphical programs. The following are some of the more popular Python GUI
the Spotlights for this
libraries.
course on their CHOICE

D
Course screen after
class for supplemental Library Description
information and tkinter Uses the TK graphical library and is the default GUI library included as part
additional resources.
GUI Libraries
Point out that the
standard Python library
PyGTK or
of the standard Python suite.
Uses the GTK+ graphical library, used mainly in the GNOME desktop
environment in Linux®.
e
includes the tkinter
package by default, so PyQT Uses the Qt graphical library, which is used mainly in the KDE desktop
at

students will use that environment in Linux.


library in this lesson's wxPython Uses the wxWidgets graphical library, which is a multiplatform graphical
activities. After students
environment.
lic

become familiar with one


package, it's not too
difficult to use others. It's a good idea to consider which library you'll use before you design an application's user interface,
since the libraries vary somewhat.
up

User Interface Objects


D

User Interface Objects When you make the move to GUI programming, you need to learn a new set of terms. For example,
This section defines the main area in a window is typically called the frame. The frame contains all of the objects the
standard Windows terms program uses to interact with the user, and it is the central part in a GUI program. The frame is
ot

as used by Python. composed of objects called widgets (short for window gadgets) that display and retrieve information.
Some students may be Most graphical programming languages provide a library of widgets for you to use in your programs.
familiar with other Although not an official standard, a common set of widgets is available in just about every graphical
N

programming languages programming environment.


that use other terms for
the same objects.
Widget Description
o

Button Triggers an event in the window when selected.


D

Check button Allows the user to select or deselect an individual item.


Entry Provides an area to enter or display a single line of text.
Label Places static text in the window.
List box Displays multiple values to select one or more items.

Lesson 2: Creating a GUI | Topic A


Python® Programming: Advanced | 35

Widget Description
Menu Displays a menu toolbar at the top of the window.
Progress bar Indicates that something is happening in the background.
Radio button Allows the user to select one item from a group.
Scroll bar Controls the viewed items in a list box or frame.
Separator Places a horizontal or vertical bar in the window.

e
Spin box Allows a user to select a value from a range of numbers.

ut
Text Provides a large area to enter or display multiple lines of text.

ib
Each widget has its own set of properties that define how it appears in the window and how to
handle any data or actions that occur while the user interacts with the widget. Before you start to
code your user interface, it's a good idea to plan your layout on paper or in a wireframe drawing tool.

tr
Guidelines for Planning a User Interface

is
Note: All Guidelines for this lesson are available as checklists from the Checklist tile on the

D
CHOICE Course screen.

Use the following guidelines to help when planning a graphic user interface design. Guidelines for Planning
• To identify the widgets you require:
• Determine what data the application needs to collect from the user. or
• Determine the most appropriate widget to use for each data value the user must provide. (For
a User Interface
e
example, use a radio button when the user should select a single object from a group of
options.)
at

• Determine what actions will trigger the processing of the input data, and what widgets will be
involved. (For example, the user selects a Calculate price button.)
lic

• Determine what widgets will display the program results.


• Before you start development, make sure you select a GUI library that:
• Provides a wide selection of widgets of the types you need to use.
up

• Provides a look and feel that you and your users will like to use.
• Provides licensing options that are acceptable for your purposes.
• Is compatible with all of the operating systems and distribution methods you need to support
D

for your finished application.


ot
N
o
D

Lesson 2: Creating a GUI | Topic A


36 | Python® Programming: Advanced

ACTIVITY 2-1
Designing a GUI

Scenario

e
You've been asked to design an application, the Python Pizza Calculator, which helps customers

ut
of a pizza restaurant determine the cost of the type of pizza they are interested in ordering. To do
that, you'll need to create a window with widgets to allow customers to select the size of pizza they
want (medium, large, or extra large), along with choosing from a list of available toppings. Once

ib
customers select their pizza options, they'll be able to view the total cost for the pizza.
Activity: Designing a GUI The user interface will include some means to do the following:

tr
• Choose a size (just one):
• Medium

is
• Large
• Extra Large

D
• Choose toppings (none, one, or more than one):
• Sausage
• Pepperoni
• Chicken
• Mushroom
• Onion
or
e
• Black Olive
at

• Green Pepper
• Red Pepper
• Clear all selections (reset).
lic

• Display the total price.


up

1. Consider the following questions as you plan the layout for the Python Pizza Calculator.
Discuss these questions
with the entire class or 2. How many windows will the application use?
consider dividing
D

A: While applications may have multiple windows, this application is simple enough that it can be
students into teams. implemented in one window.
Consider having
students use Paint,
ot

® 3. What type of widget(s) might you provide to enable the user to select a pizza size?
PowerPoint , or a
wireframe diagramming A: Since only one size should be selected from the three options, a group of radio buttons is probably
tool to design the layout, the most appropriate choice for this. Another option would be a list box configured to allow only
N

if they have access to one item to be selected.


any of this software.
4. What type of widget(s) might you provide to enable the user to select toppings?
o

A: Since no selection, one selection, or multiple selections should be allowed, a group of check
boxes would be an appropriate choice for this. Another option would be a list box configured to
D

allow multiple items to be selected.

5. What type of widget(s) might you provide to enable the user to clear (reset) the selections?
A: A button would be appropriate for this. When selected, a Reset button could trigger an action that
resets the application widgets back to their original selection states.

Lesson 2: Creating a GUI | Topic A


Python® Programming: Advanced | 37

6. What type of widget(s) might you provide to enable the user to calculate the total?
A: A label or text box could be used to display the resulting price. There are different ways to trigger
the calculation. For example, you might calculate a new result automatically each time the user
changes the size or toppings. Or you might provide a separate Calculate price button that displays
the updated total when the user selects the button.

7. Create a wireframe to depict the layout.


a) In your course manual's margins or in a drawing application, create a wireframe sketch of the
Python Pizza Calculator user interface.

e
PPC Wireframe

ut
After students complete
their diagrams, have
them present them to
the group and/or display

ib
the slide showing an
example wireframe

tr
diagram.
While there are various
ways to implement the

is
user interface, point out
that the slide represents

D
the design that will be
used in the activities that
follow.

or
e
at
lic
up
D
ot
N
o
D

Lesson 2: Creating a GUI | Topic A


38 | Python® Programming: Advanced

TOPIC B
Create and Arrange a GUI Layout
Once you've come up with a layout for your GUI application and have selected a GUI library that
you'll use to develop it, you're ready to start programming your layout.

e
Tkinter Library

ut
Tkinter Library The tkinter library provides a standard class and methods for creating windows and widgets. Just
import all of the items in the tkinter module, and instantiate the Tk() class:

ib
from tkinter import *
window = Tk()

tr
window.title("This is a test window")
window.geometry("300x100")

is
This code creates a window, and sets the title and size of the window, which is straightforward.
However, before you can add widgets to the window, you must create a frame by defining a subclass

D
of the tkinter Frame class:
class Application(Frame):
def __init__(self, master):

self.create_widgets()

window = Tk()
or
super(Application, self).__init__(master)
e
window.title("Test Application Window")
at

window.geometry("300x100")
app = Application(window)
app.mainloop
lic

This code template defines the class Application as a subclass of the tkinter Frame class. It then
uses the empty Tk() instance as the parent class for the app instance.
After instantiating the new window, the mainloop() method is called. It enters into an endless
up

loop, listening for window events, and passing them to event handler methods defined in the
program.
D

Guidelines for Defining Widgets


Once you define the frame for the window, you can start adding widgets.
ot

Reference the Widget


Method Reference the Widget Method
N

You must create a single method that creates all of the widget objects in the frame. First, define the
method name in the Application constructor:
class Application(Frame):
o

def __init__(self, master):


D

super(Application, self).__init__(master)
super.create_widgets()

Define the Widget


Method Define the Widget Method
You must create a separate method to create all of the window widgets within the subclass
definition:
def create_widgets(self):

Lesson 2: Creating a GUI | Topic B


Python® Programming: Advanced | 39

Define Labels
Define Labels
To place text in the window, use the Label widget. The Label widget uses a single parameter
named text to define the text placed in the window:
self.text1 = Label(self, text="This is the text in the window")

Define Buttons
Define Buttons
The Button widget provides a way for application users to trigger event handlers in the application,

e
such as to let the program know when there's data to submit. You must assign the Button widget to

ut
a unique variable created in the Application subclass. The Button widget uses two parameters—
the text that's placed inside the button, and the command parameter, that defines the method that's
called when the button is pressed:

ib
self.button1 = Button(self, text="Submit", command=self.calculate)

Define Entry Widgets

tr
Define Entry Widgets
The Entry widget is one of the most versatile widgets you'll use in your programs. It creates a

is
single-line form field that the user can use to enter text to submit to the program, or your program
can use to display text dynamically in the window. The Entry widget doesn't require any parameters,

D
but often the width parameter is used to set the number of characters to place in the viewable area
(you can enter more characters in the Entry form field, as they will scroll within the field):
self.entry1 = Entry(self, width=20)

Define Text Boxes or


For entering large amounts of text, you can use the Text widget. It provides for multi-line text
Define Text Boxes
e
entry, or displaying multiple lines of text from your program. As with the Entry widget, the Text
widget doesn't require any parameters, but most likely you'll want to add the parameters to set the
at

width and height of the text box that it creates in the window:
self.field1 = Text(self, width=20, height = 10)
lic

Define Radio Buttons


Define Radio Buttons
The Radiobutton widget provides a one-from-many selection option in the window. Radio buttons
up

are normally grouped together to form a group of options where only one option from the group
can be selected. Use the text parameter to specify the label that appears next to the radio button,
and the value parameter to specify the value that's passed to the event handler when the radio
D

button is selected. To specify which radio buttons are grouped together, you use the variable
parameter to specify the same variable for the group of buttons:
self.button1 = Radiobutton(self, text="Option 1", variable=result, value="1")
ot

self.button2 = Radiobutton(self, text="Option 2", variable=result, value="2")


self.button3 = Radiobutton(self, text="Option 3", variable=result, value="3")
N

Define Check Boxes


Define Check Boxes
The Checkbutton widget provides an on-or-off type of interface. If the Checkbutton widget is
o

checked by the user, it returns a True value, and if the widget is not checked, it returns a False
value. The parameters for the Checkbutton widget are text to display the label that appears next to
D

the check box, and variable, to define the variable that returns the Checkbutton state:
self.option1 = Checkbutton(self, text="Option 1", variable=option1)

Define Multiple Check


Define Multiple Check Boxes Boxes
Often, check boxes are used in long lists of options to allow the program user to select which items
from the list to use. Instead of coding individual Checkbutton lines, which can get tedious for long

Lesson 2: Creating a GUI | Topic B


40 | Python® Programming: Advanced

lists, you can easily use a list to contain the options, and use a loop to iterate through the list and
create the Checkbutton lines. To do that, you'll need to create a separate list to hold the individual
Checkbutton widget objects, and the variables that they each return. This can get a little confusing,
but using some common-sense list names helps:
self.options = ["Option 1", "Option 2", "Option 3", "Option 4"]
self.checkbox = list(self.options)
self.checkboxVar = list(self.options)
for option in range(len(self.options)):
self.checkbox[option] = Checkbutton(self,

e
text=options[option],

ut
variable=self.checkboxVar[option])

Window Positioning Methods

ib
Window Positioning The key to a user-friendly GUI application is the placement of the widgets in the window area. Too

tr
Methods many widgets grouped together can make a user interface confusing. The tkinter package provides
three ways to position widgets in the window:

is
• Packing widgets into available spaces in the window
• Using positional values

D
• Using a grid system
The packing method pretty much does what it says. It attempts to pack widgets into a window as best
it can in the space available. When you choose this method, Python places the widgets in the

or
window for you, starting at the top-left of the window and moving along to the next available space,
either to the right or below the previous widget. The packing method works fine for small windows
with just a few widgets, but if you have lots of widgets, things can get pretty cluttered.
e
The positional method requires that you define the precise location of each widget, using X and Y
coordinates within the window. This provides the most accurate control over where the widgets
at

appear, but it can be somewhat difficult to work with.


The compromise between the packing and positional methods is the grid method. The grid method
lic

creates a grid system in the window using rows and columns, somewhat like a spreadsheet. You
place each widget in the window at a specific row and column location:
self.text1 = Label(self, text="This is some window text")
up

self.text1.grid(row=0, column=0)
You can also define a widget to span multiple rows or columns:
self.text1.grid(row=0, columnspan=3)
D

The grid method also defines the sticky property. This determines where in the cell the widget is
positioned (N for top-aligned (north), S for bottom-aligned (south), E for right (east), and W for left
(west).
ot

The grid method provides some important benefits, such as:


• It forces the developer to consciously plan out the user interface, perhaps even using a pencil-
N

and-paper approach to plan columns and rows where widgets should appear. For developers
coming from visual layout environments like Xcode® or Visual Studio®, this approach seems
familiar.
o

• It tends to adapt the layout well when the window size is changed by the user.
D

Guidelines for Window Positioning Methods


Guidelines for Window Select the method best suited for your application. For most simple layouts, the grid method
Positioning Methods provides overall control over where the widgets appear in the window, without making you
determine exact window coordinates for each widget. Here are the rules for using the grid method:
• Define the grid positioning method in the Application subclass:

Lesson 2: Creating a GUI | Topic B


Python® Programming: Advanced | 41

class Application(Frame):
def __init__(self, master):
super(Application, self).__init__(master)
super.grid()
super.create_widgets()
• Define the grid location for each widget as you create it:
def create_widgets(self):
self.label1 = Label(self, text="Welcome to my window")

e
self.label1.grid(row=0, column=0, sticky=W)
self.button1 = Button(self, text="Click me!", command=self.display)

ut
self.button1.grid(row=1, column=0, sticky=W)
self.output = Entry(self, width=10)
self.output.grid(row=2, column=0, sticky=W)

ib
tr
is
D
or
e
at
lic
up
D
ot
N
o
D

Lesson 2: Creating a GUI | Topic B


42 | Python® Programming: Advanced

ACTIVITY 2-2
Creating the Python Pizza Calculator GUI
Application Window

e
Scenario

ut
You have settled on a layout for the Python Pizza Calculator window. You will start by creating a
new project folder. Then, you will develop the layout using the tkinter library.

ib
Activity: Creating the
Python Pizza Calculator
GUI Application Window 1. Launch PyCharm and create a new project.

tr
a) From the desktop, double-click the JetBrains PyCharm Community Edition 3.4 shortcut.
b) In the PyCharm Community Edition window, select Create New Project.

is
c) In the Create New Project dialog box, in the Project name text box, type PizzaCalculator
d) Next to the Location field, select the Browse button to open the Select Location for Project Directory

D
dialog box.
e) In the top-left corner of the Select Location for Project Directory dialog box. select the Home

Directory button to select your user directory.

beneath it. or
f) Under your user name, select the triangle next to the Desktop directory to show subdirectories

g) Beneath the Desktop directory, select the triangle next to the AdvPython directory to show
e
subdirectories beneath it.
h) Beneath the AdvPython directory, select the Creating a GUI directory.
at

i) Select OK to return to the Create New Project dialog box.


j) Select OK to create the new project.
lic

k) On the left side of the PyCharm window, in the Project window, verify that PizzaCalculator is listed.

2. Create the ppc.py file in the PizzaCalculator project.


a) In the left window, right-click on the PizzaCalculator project name.
up

b) Select New→Python file from the menu.


c) In the Name text box, type ppc
d) Select OK to create the file.
D

3. Define the Application subclass.


a) At the top of the open ppc.py file, type the code to import the methods from the tkinter library,
ot

and define the Application subclass of the Frame class.


N
o
D

Lesson 2: Creating a GUI | Topic B


Python® Programming: Advanced | 43

b) After the class definition, type the code to create the constructor.
If you would prefer that
you or your students not
type the code in step 3b,
you can copy it from
SNIPPET 1, provided in
Snippets.txt.

e
ut
ib
tr
is
D
or
e
at

The constructor defines a list object that contains the pizza toppings, and list objects for the
checkbuttons and the checkbutton variables.
lic

4. Define the application widgets.


a) After the constructor, add the create_widgets() method and the first label by entering the
up

following code.
If you would prefer that
you or your students not
D

type the code in step 4a,


you can copy it from
SNIPPET 2, provided in
Snippets.txt.
ot
N
o
D

Lesson 2: Creating a GUI | Topic B


44 | Python® Programming: Advanced

b) Add the code to define the three radio buttons used to select the pizza size.
If you would prefer that
you or your students not
type the code in step 4b,
you can copy it from
SNIPPET 3, provided in
Snippets.txt.

e
ut
ib
tr
is
D
or
All of the buttons will be on the same line, and will be tied to the same variable. The Radiobutton
e
select() method is called to make the Medium the default size selection.
c) Add the code to create a new label to identify the pizza toppings list, and the code to iterate through
at

the toppings list to create the topping check boxes.


If you would prefer that
lic

you or your students not


type the code in step 4c,
you can copy it from
SNIPPET 4, provided in
up

Snippets.txt.
D
ot
N

A separate variable is used to keep track of the row numbers dynamically in the loop.
o
D

Lesson 2: Creating a GUI | Topic B


Python® Programming: Advanced | 45

d) After the checkbox loop, add the code to create the two buttons to reset the form, and calculate the
pizza price.
If you would prefer that
you or your students not
type the code in step 4d,
you can copy it from
SNIPPET 5, provided in
Snippets.txt.

e
ut
ib
e) After the buttons, add code to create an empty line in the grid layout by creating a Label with no
text.

tr
If you would prefer that
you or your students not

is
type the code in step 4e,
you can copy it from
SNIPPET 6, provided in

D
Snippets.txt.

or
f) Finally, after the empty line, add code to set the Total label, and an Entry box to display the total
price.
e
If you would prefer that
you or your students not
at

type the code in step 4f,


you can copy it from
SNIPPET 7, provided in
lic

Snippets.txt.
up
D

5. Now that you've completed the Application subclass, instantiate the Tk() class, create the
Application subclass instance, and start the main loop. Add code to set the window title and size.
ot

If you would prefer that


you or your students not
type the code in step 5,
N

you can copy it from


SNIPPET 8, provided in
Snippets.txt.
o
D

Note: You may have to experiment with the width and height settings depending
on your desktop default fonts.

Lesson 2: Creating a GUI | Topic B


46 | Python® Programming: Advanced

6. Run the Python Pizza Calculator application.


a) Run ppc.py.

e
ut
ib
tr
is
D
or
e
b) Select the different pizza size radio buttons to make sure you can only make one selection.
at

c) Select and deselect each toppings' check box to make sure they all work.
For now, nothing will happen when you select the Reset or Calculate Price buttons, as you haven't
defined any event handlers.
lic

a) In the top-right corner of the window, select the X to close the window and end the program.
up
D
ot
N
o
D

Lesson 2: Creating a GUI | Topic B


Python® Programming: Advanced | 47

TOPIC C
Interact with User Events
You have created a window that contains various user interface components (widgets). Now, you
will populate those components with content and enable them to interact with the user.

e
Events

ut
Programming for a GUI environment is a bit different from command-line programming. In a Events
command-line program, the order of the program code controls what happens next. For example,

ib
the program has code that prompts the user for input, then processes the input, and then displays
the results on the command line based on the input provided. The user can only respond to the

tr
input requests as they are presented by the program.
In contrast, a GUI program displays an entire set of interaction widgets all at once, all in the same

is
window. The program user gets to decide which widget gets processed next. Because the program
doesn’t control which widget is activated at any given time, this process is called event-driven
programming. In event-driven programming, Python calls different methods within the program,

D
based on which event (or action) occurs in the GUI window. There isn’t a set flow to the program
code; it’s just a bunch of methods that individually run in response to an event.

or
For example, your user can enter data into a text widget, but nothing happens until the user presses
a button in the program window to submit the text. The button triggers an event, and your program
code must detect that event and then run the code method to read the text in the text widget and
process it.
e
at

Event Handlers
The key to event-driven programming is linking widgets in the window to events, and then linking Event Handlers
lic

events to code methods in the program. These methods are called event handlers. You must create
separate event handler methods for each event that can be generated from the widgets in the
window. The event handlers do the bulk of the work in GUI programs. They retrieve the data from
up

the widgets, process the data, and then display the results in a window using other widgets. This
might seem a bit cumbersome at first, but once you get used to coding with event handlers, you’ll
see just how easy it is to work in a GUI environment.
Event handlers are class methods created in the Application subclass that handle events generated
D

by widgets. You must define the event handler name inside the widget using the command parameter:
self.button1 = Button(self, text="Submit", command=self.display)
ot

The actual event handler is a separate method that you must create inside the Application
subclass:
N

def display(self):
print("The button was clicked")
It's imperative that you match the command name defined in the widget to the method name,
o

including the text case.


D

Guidelines for Interacting with Widgets


Follow these guidelines for interacting with various types of widgets.

Lesson 2: Creating a GUI | Topic C


48 | Python® Programming: Advanced

Respond to a Button
Click Respond to a Button Click
When you create a Button widget, use the command parameter to define the event handler method
that Python will call when the program user selects the button:
self.button1 = Button(self, text="submit", command=self.display)

Read the Value Entered


into an Entry Widget Read the Value Entered into an Entry Widget
To retrieve the value entered into an Entry widget you use the get() method on the Entry widget

e
object. You can also display data from your program in an Entry widget by using the insert()

ut
method, or clear out any text already in the Entry widget by using the delete() method. The
delete() method uses two parameters—the starting character position (with the first character at
position 0), and the end position (you can use the special keyword END). The insert() method also

ib
uses two parameters—the starting location of the inserted text, and the text to insert into the widget:
def convert(self):

tr
varText = self.text1.get()
varReplaced = varText.upper()

is
self.text1.delete(0, END)
self.text1.insert(END, varReplaced)

Determine the Value

D
Returned by a Determine the Value Returned by a Radiobutton Widget
Radiobutton Widget
Radiobutton widgets must use a control variable to pass the radio button state. Python defines four
types of control variables:
or
• BooleanVar()—for Boolean True and False values.
• DoubleVar()—for floating point values.
e
• IntVar()—for integer values.
• StringVar()—for text values.
at

Read the Value of the


Selected Radiobutton Read the Value of the Selected Radiobutton
lic

Group radio buttons together by using the same control variable for each radio button in the group.
To retrieve the value of the selected radio button from the group, use the get() method for the
control variable. The get() method retrieves the value parameter specified for the selected
up

Radiobutton object:
def create_widgets(self):
self.var1 = StringVar()
D

self.radio1 = Radiobutton(self, text=”Option 1”, variable=self.var1,


value=”1”)
self.radio2 = Radiobutton(self, text=”Option 2”, variable=self.var1,
ot

value=”2”)
self.radio3 = Radiobutton(self, text=”Option 3”, variable=self.var1,
value=”3”)
N

def process(self):
selection = self.var1.get()
if (selection == “1”):
o

print(“Option 1 was selected”)

Read the State of a


D

Checkbutton Widget Read the State of a Checkbutton Widget


The Checkbutton widget also uses a control variable, but it doesn't return a value, it just returns a
Boolean True value if the check box is selected, or a False value if it's not selected. Thus, you use
the BooleanVar() control variable type for the Checkbutton widget. You use the get() method
for the control variable to determine the state of the check box at the time of an event trigger:

Lesson 2: Creating a GUI | Topic C


Python® Programming: Advanced | 49

def create_widgets(self):
for i in range(len(self.options)):
self.checkboxVar[i] = BooleanVar()
self.checkbox[i] = Checkbutton(self, text=self.options[i],
variable=self.checkboxVar[i])

def process(self):
for box in range(len(self.options)):
if (self.checkboxvar[box].get()):

e
print(“%s was selected”.format(self.options[box]))

ut
Read the Value Entered
Read the Value Entered into a Text Widget into a Text Widget
As with the Entry widget, you retrieve text from the Text widget using the get() method, remove

ib
text using the delete() method, and add text using the insert() method. However, there’s a bit
of a twist to these methods in the Text widget. Because the widget works with multiple lines of text,

tr
the index value you specify is not a single value. Instead, it’s a text value that has two parts: "x.y".
The x is the row location (starting at 1), and y is the column location (starting at 0). So, to reference

is
the first character in the Text widget, you use the index value of "1.0":
def create_widgets(self):
self.text1 = Text(self, width=20, height=10)

D
def process(self):
varText = self.text1.get("1.0", END)
varReplaced = varText.upper()
self.text1.delete("1.0", END)
self.text1.insert(END, varReplaced)
or
e
Menu Bars
at

A staple of GUI programs is the menu bar at the top of the window. The menu bar provides drop- Menu Bars
lic

down menus so program users can quickly make selections. You use the Menu widget to create menu
bars in your tkinter programs.
First, define a main Menu instance. After that, you can add main menu bar top-level entries by
up

creating subclass instances of the main Menu instance. For menu entries that contain sub-menus, use
the add_cascade() method to add the entry. For menu entries that point directly to event handlers,
use the add_command() method.
D

menubar = Menu(self)
filemenu = Menu(menubar)
filemenu.add_command(label="New", command=self.new)
ot

filemenu.add_command(label="Open", command=self.open)
filemenu.add_command(label="Quit", command=self.quit)
menubar.add_cascade(label="File", menu=filemenu)
N

menubar.add_command(label="Help", command=self.help)
window.config(menu=menubar)
o

Guidelines for Handling User-Submitted Data


D

Follow these guidelines when handling user-submitted data.


User-Submitted Data
User-Submitted Data
When handling user-submitted data:
• Don't trust data entered by users into form fields. Many attackers intentionally enter erroneous
data just to see what your program will do, hoping to gain unauthorized access to data.

Lesson 2: Creating a GUI | Topic C


50 | Python® Programming: Advanced

• If you allow your program users to enter free-form data into entry or text form fields, always
validate the entered data before using it in your application:
• For numeric fields, check that all of the characters are numbers using the Python
isnumeric() method.
• Also for numeric fields, validate the number of digits if necessary, such as the number of
digits needed for zip codes.
• For text fields, check for special characters, such as backslashes and semicolons. These are
often used to fool databases into performing unwanted actions.

e
• If your application supports HTML text, watch for embedded URL addresses in the data that
can lead other users to inappropriate websites.

ut
ib
tr
is
D
or
e
at
lic
up
D
ot
N
o
D

Lesson 2: Creating a GUI | Topic C


Python® Programming: Advanced | 51

ACTIVITY 2-3
Creating a Simple Window Form

Before You Begin

e
The PizzaCalculator project is open in PyCharm.

ut
Activity: Creating a
Scenario Simple Window Form
You are considering adding a form to the Python Pizza Calculator to enable users to provide

ib
delivery instructions. You will create a new window that prompts the user to provide the delivery
information.

tr
is
1. Create the deliveryform.py file in the PizzaCalculator project.
a) In the left window, right-click on the PizzaCalculator project name.
b) From the menu, select New→Python file.

D
c) In the Name text box, type deliveryform
d) Select the OK button to create the file.

2. Create the Application subclass constructor.


or
a) At the top of the open deliveryform.py code file, type the code to import the methods from the
tkinter library, and define the Application subclass of the Frame class.
e
If you would prefer that
you or your students not
at

type the code in the step


2 sub-steps, you can
copy it from SNIPPET 9,
lic

provided in Snippets.txt.
up

b) After the class definition, type the code to create the constructor.
D
ot
N
o
D

The application will use the grid positioning method, and will use create_widgets() to define the
widgets.

3. Define the widgets used for the application.

Lesson 2: Creating a GUI | Topic C


52 | Python® Programming: Advanced

a) Define the create_widgets() method, and a menu bar that has two top-level entries: File and
Quit. The File entry will have a sub-entry named Submit.
If you would prefer that
you or your students not
type the code in step 3a,
you can copy it from
SNIPPET 10, provided
in Snippets.txt.

e
ut
ib
b) Inside the create_widgets() method, define the label that prompts the user to enter the delivery
instructions, the Entry widget to accept the input, and the Submit button to trigger the event

tr
handler called process. After those items are created, add a line to add the menu bar item to the
window.

is
If you would prefer that
you or your students not
type the code in step 3b,

D
you can copy it from
SNIPPET 11, provided
in Snippets.txt.

or
e
at
lic
up

4. After the constructor code, define the process event handler that retrieves the instructions entered into
D

the Entry widget, creates a message string, and displays the message in the output Entry widget.
If you would prefer that
you or your students not
ot

type the code in step 4,


you can copy it from
SNIPPET 12, provided
N

in Snippets.txt.
o
D

5. Add the code to instantiate the Tk() class, and the Application subclass, defining the window title
and size. Then, add the mainloop() method to listen for events.
If you would prefer that
you or your students not
type the code in step 5,
you can copy it from
SNIPPET 13, provided
in Snippets.txt.

Lesson 2: Creating a GUI | Topic C


Python® Programming: Advanced | 53

e
ut
6. Run the deliveryform application.
a) Run the deliveryform.py script.

ib
The Pizza Delivery Instructions window is shown, and the text box is ready for you to type delivery
instructions.
b) Type knock twice (the doorbell is broken)

tr
c) Select the Submit button, or select File→Submit from the application menu bar. The message
appears at the bottom of the window.

is
D
or
e
d) Close the Pizza Delivery Instructions window to exit the application and return to PyCharm.
at

e) Close the deliveryform.py editor tab.


lic
up
D
ot
N
o
D

Lesson 2: Creating a GUI | Topic C


54 | Python® Programming: Advanced

ACTIVITY 2-4
Adding Data Processing to the Python Pizza
Application

e
Before You Begin

ut
The PizzaCalculator project is open in PyCharm.
Activity: Adding Data

ib
Processing to the Scenario
Python Pizza Application
You have laid out the controls for the Python Pizza Calculator, but at this point, they are not yet

tr
functional. You will add an event handler to calculate the cost of the pizza based on the selections
the program user makes from the size and toppings widgets. The pizza cost will be based on a
Medium pizza being $9.99, with each additional topping $1.00, a Large pizza being $12.99, with each

is
additional topping $1.50, and an Extra Large pizza being $14.99, with each additional topping $1.80.
A dictionary object that holds the pizza prices for the calculations has already been added to the

D
project.

1. Examine the prices dictionary object.


or
a) In ppc.py, examine the self.prices dictionary object.
e
at
lic
up
D

The dictionary uses the product description as the key and the price as the value.
ot

2. Define the event handler methods in the Button widgets.


N
o
D

Lesson 2: Creating a GUI | Topic C


Python® Programming: Advanced | 55

a) Add command parameters to the Reset and Calculate Price button widgets to point to the methods
that will handle their button clicks.

e
ut
ib
3. Define the reset() method to clear the total field form, select the Medium pizza size, and deselect all

tr
of the Checkbutton widgets.
a) After the create_widgets() method, but before the code to instantiate the window, insert a new

is
reset() method, as shown.
If you would prefer that
you or your students not

D
type the code in step 3,
you can copy it from
SNIPPET 14, provided

or in Snippets.txt.
e
at

This method selects the Medium pizza size, deselects each of the topping Checkbuttons, and
lic

deletes the existing text in the totals Entry widget.

4. Define the calculate() method to calculate the total pizza cost.


up
D
ot
N
o
D

Lesson 2: Creating a GUI | Topic C


56 | Python® Programming: Advanced

a) After the reset() method, but before the code to instantiate the window, add a new calculate
method, as shown.
If you would prefer that
you or your students not
type the code in step 4,
you can copy it from
SNIPPET 15, provided
in Snippets.txt.

e
ut
ib
tr
is
D
• Lines 90 through 93 determine how many toppings were selected by iterating through all of the
Checkbutton variables in the list, using the get() method to determine if they are checked or
not. Self.totalToppings keeps a running total.


or
Lines 95 through 100 determine which size of pizza was selected, and calculates the total price
of the pizza, using the get() method to check the value returned by the Radiobutton group
and calculate the price based on each size group.
Lines 102 through 104 display the total price, rounding the floating point value to two decimal
e
places, and converting it into a string value to display in the Entry widget.
at

5. Run the updated Python Pizza Calculator application.


a) Run ppc.py.
lic
up
D
ot
N
o
D

Lesson 2: Creating a GUI | Topic C


Python® Programming: Advanced | 57

b) Select a pizza size and the toppings you want on your pizza. Select Calculate Price, and the total
cost should appear in the Total field.

e
ut
ib
tr
is
D
or
e
c) Select the Reset button to ensure the form fields are reset.
at

6. Clean up the workspace.


a) Close the Python Pizza Calculator window.
lic

b) Select File→Close Project.


The project is closed.
c) Close the PyCharm Community Edition window to exit PyCharm.
up
D
ot
N
o
D

Lesson 2: Creating a GUI | Topic C


58 | Python® Programming: Advanced

Summary
In this lesson, you used the Python tkinter library to create graphical windows with Python code.
You defined an Application subclass, created the constructor to define the window, and defined
the widgets that appear inside the window. Finally, you created event handlers to process window
events generated in the window by the program user.
Encourage students to
What type of Python applications benefit from using a graphical window for entering and displaying data?

e
use the social
networking tools A: Applications that require a lot of input from the program user would benefit from graphical windows. A

ut
provided on the CHOICE command line program would need to ask multiple questions to retrieve each data item from the user,
Course screen to follow which could become tedious. In a graphical window, all of the data items are displayed as form fields
up with their peers after
that the user can fill out to submit all at once to the program.

ib
the course is completed
for further discussion Will your own Python applications typically provide a graphical user interface, command-line interface, or
and resources to support browser-based (web) interface?

tr
continued learning.
A: This will vary depending on your users and requirements. Python supports a wide range of
development needs and can be used to develop any of these types of applications.

is
Note: Check your CHOICE Course screen for opportunities to interact with your classmates,

D
peers, and the larger CHOICE online community about the topics covered in this course or
other topics you are interested in. From the Course screen you can also access available
resources for a more continuous learning experience.

or
e
at
lic
up
D
ot
N
o
D

Lesson 2: Creating a GUI |


3 Using Databases

e
Lesson Time: 3 hours, 15 minutes

ut
ib
tr
Lesson Objectives

is
In this lesson, you will:

D
• Identify different ways to store data in a Python program.
• Incorporate an SQLite database in Python programs.

or
• Define basic SQL statements and how to use them.

Lesson Introduction
e
at

As you write larger Python® applications, you'll find at some point that you'll need to store
and retrieve data. Python supports different types of databases, which makes storing and
retrieving data a breeze.
lic
up
D
ot
N
o
D
60 | Python® Programming: Advanced

TOPIC A
Basics of Data Management
Storing data for long-term use in a Python program is a necessity for most applications. Fortunately,
the Python language has several libraries of functions that help with that.

e
You may want show the
Spotlight presentations Note: To learn more, view the Spotlight presentations from the Spotlight tile on the CHOICE

ut
from the CHOICE course screen.
Course screen or have
students navigate out to

ib
the Course screen and Files
watch them as a
supplement to your In some cases, it makes sense to save data in a local file. This provides the benefit of keeping data in

tr
instruction. If not, please a form that is easy to copy and share (by sharing the file that contains the data). File-based storage
remind students to visit continues to be as relevant and pervasive today as it was decades ago. Some of the most popular
the Spotlights for this

is
software applications, such as Microsoft® Office, use this approach.
course on their CHOICE
Course screen after Python has built-in functions for handling all of your file storage needs. Before you can do any

D
class for supplemental reading or writing of data in a file, your program must first open the file. You use the open()
information and function to open a file:
additional resources.
myfile = open(‘textfile.txt’, ‘mode’)
Files

or
The first parameter specifies the file to open, and the second parameter specifies the mode to open
it in. The mode defines the privileges the program has for interacting with the data file. There are
four different modes.
e
Mode Description
at

r Read-only access.
w Write-only access. The file specified is replaced if it already exists.
lic

r+ Read and write access.


a Write only, but append new data to the end of an existing file.
up

The open() function returns a special value called a file pointer. After you open the file, you can use
the file pointer to reference the opened file in any read or write operations.
D

To write new data to the file, use the write() method:


myfile.write(“This is a test”)
ot

Python writes the specified data directly to the file at the location of the file pointer.
Reading data from a file is a little trickier. There are two ways to read data from a flat file. The
read() method allows you to specify how many characters to read from the file:
N

test = myfile.read(4)
This returns the first four characters in the file. Working your way through a file character-by-
o

character can be somewhat challenging. To make life easier, Python also includes the readline()
function. The readline() function reads the file one line at a time:
D

test = myfile.readline()
This is an excellent way to process text files.
When the file pointer gets to the end of the file, both the read() and readline() functions return
a NULL value, letting you know that there's no more data.
When you're done using the file, you should close the file pointer by using the close() function:

Lesson 3: Using Databases | Topic A


Python® Programming: Advanced | 61

myfile.close()

Database
The downside to simple file-based storage is that it's hard to search for specific data. You have to Database
read each line one-by-one and check the data to find what you're looking for. For applications that
need to do a lot of searching for data, this can become slow and tedious. This is where databases
come in.

e
A database stores data in a file, but uses a separate database engine program that interfaces with the
data file to do all the hard work of reading, writing, and looking for data for you. All your program

ut
needs to do is tell the database engine what you're looking for, and the database engine does the rest.
Python supports many different database engines. The following are some of the more popular

ib
ones.

Database Description

tr
Microsoft® SQL The commercial Microsoft database server that supports medium-to-
Server®

is
large database applications.
Oracle® A commercial database commonly used in Unix® environments.

D
MySQL™ A popular open source database commonly used in websites.
PostgreSQL® A popular open source database that incorporates advanced database
features.
or
For simple database applications, though, Python also supports the SQLite database engine. SQLite
(now called SQLite3 for the current version) is a lightweight engine that runs as a Python library
e
behind the scenes in your application. It’s great for applications that just need a simple local
database to store application data.
at

The key to using a database is the ability to submit simple commands to the database engine, and
receive the results. Most modern databases support a common Structured Query Language (SQL)
lic

for doing just that. The SQL standard defines simple text commands that clients can submit to a
database server to create databases and tables, insert data, and query data values.
up

Tables and Data Fields


The key to a structured database comes in structuring the data for easy access. The relational Tables and Data Fields
database method of storing data organizes the data into data fields and groups common data fields
D

into tables.
Data fields define the individual data elements in an application. Items such as your name, age,
ot

address, and phone number are stored in the database as data fields.
Each data field is created using a specific data type. The data type defines how the data is stored in
the database. The following are common data types.
N

Data Type Values Stored


o

Integer Whole numbers


D

Floating Point Values with decimal places


Character Standard text that's usually a set size (such as a zip code)
Variable Character Standard text that can vary in length (such as a name)
Date Dates
Date/Time Dates and times

Lesson 3: Using Databases | Topic A


62 | Python® Programming: Advanced

Guidelines for Creating Tables


Note: All Guidelines for this lesson are available as checklists from the Checklist tile on the
CHOICE Course screen.

Guidelines for Creating The first part of any project that uses data should be to design the database tables that are required.
Tables There are some steps that you should take with that process:
• Determine the different data elements required for the application.

e
• Divide the data elements into common groups (called data normalization).
• Determine the data type required to store each data element.

ut
• Determine a primary key for each table.
• Create a separate database for each application.

ib
• Create the tables and data fields.

tr
is
D
or
e
at
lic
up
D
ot
N
o
D

Lesson 3: Using Databases | Topic A


Python® Programming: Advanced | 63

ACTIVITY 3-1
Designing a Database for Python Pizza

Scenario

e
Instead of storing the toppings list and prices inside the Python Pizza Calculator program code,

ut
you decide it's better to use a separate database to store the values. That way, you can just modify
the database records whenever there are price changes, instead of having to recode the application.
You decide on using the SQLite3 database engine to create a database to store the list of toppings

ib
and the prices for the different pizza sizes and toppings.
Activity: Designing a
Database for Python

tr
1. What data elements will be needed in the database? Pizza
For this activity, consider

is
A: For the Python Pizza Calculator, three data elements will be needed: the list of toppings, the pizza
price for each size, and the price for toppings for each pizza size. having students work in
groups and reconvene
with the entire class to

D
2. What groups of common data will be needed to contain the data elements?
discuss their
A: The data normalization process can be somewhat subjective and tricky. First, determine the conclusions.
common groups for the data. While there may be various ways of doing this, for the Python Pizza

3. Which data elements belong to which group?


or
Calculator, you'll provide two general categories of data elements: toppings and prices.

A: For the toppings group, you'll just have the topping data element. For the prices group, you'll need
e
to specify the price, and what the price is for (the product). That makes for two data elements—the
product and the price.
at

4. What data type will be required for each element?


lic

A: Again, there is some flexibility here, but in the next activity, you'll store the topping name as a text
value using the varchar data type. Since the topping names aren't too long, you'll use a 15-
character data constraint. For the product data field, you'll store the pizza size and topping size as
a text value, again using the varchar data type. You'll also use the 15-character data constraint
up

for this data field. For the price data field, you'll need to store the product price as a dollar amount,
including two decimal places for the cents. You'll use the decimal data type to do that.
D
ot
N
o
D

Lesson 3: Using Databases | Topic A


64 | Python® Programming: Advanced

TOPIC B
Use SQLite Databases
SQLite databases provide simple database features for an application without requiring an external
database server. The SQLite database engine runs using libraries included with your Python program
and uses a single database file that can be included with your application.

e
ut
SQLite3
SQLite3 SQLite3 provides a lightweight SQL database engine. It does not require a separate server process.

ib
It provides your Python programs with the ability to use common SQL commands to read and write
data to an ordinary data file that works like a database, providing multiple tables, indexes, triggers,

tr
and views. The database file format is cross-platform, which means you can freely copy a database
between 32-bit and 64-bit systems with different architectures. Because SQLite holds an entire
database in one file, you can use an SQLite database like an application file (for document sharing or

is
data transfer) or like a database (which stays on one computer, in one storage location).
While SQLite database files aren't inherently secure, there are numerous ways to improve their

D
security. For example, you can use the third-party library pysqlcipher to encrypt data stored in a
SQLite3 database file. Also, while the examples in this course are relatively simple, when you write
code to access SQLite databases (particularly when you'll have end users other than yourself), be

or
sure to include try...except handlers in your code, since there are many opportunities for things
to go awry when accessing a database file.
e
SQLite3 Database Methods
at

SQLite3 Database The SQLite database engine runs behind the scenes as needed when the Python program attempts
Methods to interact with the database. To use the SQLite methods, you must first import the sqlite3
lic

package:
import sqlite3
After you import the package, to initialize the database, you use the connect() method, specifying
up

the database file name:


conn = sqlite3.connect("mydatabase.db")
The connect() method returns a pointer to the database object that you must use when referencing
D

the database. After connecting to the database, you need to instantiate a cursor. A cursor is a pointer
that keeps track of your place in the database file. The cursor is required for all interactions with the
database. To generate a cursor, you use the cursor() method:
ot

cursor = conn.cursor()
Notice that the cursor() method is run from the database instance returned by the connect()
N

method. To submit SQL statements to the database, use the execute() method:
cursor.execute(“SELECT * From prices”)
o

Note that the SQL statement is submitted as a string value. The SQLite3 database supports
transactions, which enable you to bundle multiple SQL statements together for processing. If any one
D

of the statements fail, the other statements are rolled back to place the database in its original state.
To submit the transaction, you must use the commit() function, which is part of the connection:
conn.commit()
Finally, when you’re finished using the database, you should close out the connection handle, which
signals the SQLite3 database engine to close the database file:
conn.close()

Lesson 3: Using Databases | Topic B


Python® Programming: Advanced | 65

Database Construction
To build your application database, you’ll need to use the SQL CREATE statement. The CREATE Database Construction
TABLE statement allows you to specify the data fields as well as the data field properties that are used
in the table:
CREATE TABLE prices (product varchar(15) primary key, price decimal)
Each data field is defined within the parentheses in the order that you want them to appear in the
table. You must specify a data type for each data field. This is called a data constraint. The SQLite

e
engine will enforce all data constraints applied to data fields (for example, the varchar(15)
constraint restricts the data to only 15 characters).

ut
The PRIMARY KEY keyword is used to define the data field that will uniquely identify each data
record in the table. The SQLite3 engine will restrict new data records to ensure no two data records

ib
have the same primary key value.
After you create the table, you can insert new data using the INSERT statement:

tr
INSERT INTO prices (product, price) VALUES (‘medium’, 9.99)
The INSERT statement specifies the table to insert the data into, the data fields that are assigned

is
values, and the values assigned to each of the data fields. You use the execute() method to submit
the INSERT statement to the database. However, the INSERT statement doesn’t take effect in the
database until you also submit the commit() method:

D
sql = "INSERT INTO prices (product,price) VALUES('medium', 9.99)"
cursor.execute(sql)
conn.commit()

or
The SQLite database also supports the executemany() method. This allows you to place multiple
data values into a list, and then submit all of the data values as a single entry:
e
sql = ("INSERT INTO prices (product, price) VALUES (?, ?)")
prices = [('medium', '9.99'), ('large', '12.99'), ('x-large', '14.99')]
at

cursor.executemany(sql, prices)
The question marks in the INSERT string are replaced by each tuple value for each iteration in the
lic

list. This is the preferred method of inserting data into tables, as it helps filter out any issues with the
data.
up

Guidelines for Creating and Connecting to a Database


Follow these guidelines to create and connect to a database using the SQLite database library.
D

Create the Database


Create the database using the connect() method:
ot

conn = sqlite3.connect("mydatabase.db")

Create a Cursor for the Connection


N

Use the cursor() method to generate a cursor object:


cur = conn.cursor()
o

Submit SQL Statements Using the Cursor Object


D

Use the execute() method to submit individual SQL statements, or the executemany() to submit
groups of INSERT statements:
cur.execute("CREATE TABLE test (name varchar(15) primary key, age int)")

Commit the Transactions to the Database


Don't forget to use the commit() method to commit the SQL statements to the database:

Lesson 3: Using Databases | Topic B


66 | Python® Programming: Advanced

conn.commit()

Connect to an Existing Database


To connect to an existing database, just specify the database filename in a connect() method:
conn = connect("mydatabase.db")

Guidelines for Submitting Queries and Retrieving Results

e
Follow these guidelines when querying an SQLite3 database.

ut
Build the SELECT Statement
Create the SQL SELECT statement required to retrieve the data that you're interested in:

ib
sql = "SELECT product, price FROM prices WHERE price > 2.00"

tr
Submit the SELECT Statement
Use the SQLite execute() statement to submit the SELECT query to the database:

is
result = cur.execute(sql)

D
Retrieve the Query Results
Use the for statement to retrieve all of the data records in the query result set:
for row in result:
print("Product row[0] costs row[1].")
or
e
at
lic
up
D
ot
N
o
D

Lesson 3: Using Databases | Topic B


Python® Programming: Advanced | 67

ACTIVITY 3-2
Building a Database

Data Files

e
All project files in Desktop\AdvPython\Using Databases\PizzaCalculator

ut
Activity: Building a
Scenario Database
You will write a script that will create the SQLite database file that holds the toppings and prices

ib
used for the Python Pizza Calculator. The database will:
• Be stored in a file named pizza.db.

tr
• Include two tables:
• The toppings table, which contains:

is
• The topping field
• The prices table, which contains:

D
• The product field
• The price field

1. Launch PyCharm and open the PizzaCalculator project.


or
a) From the desktop, double-click the JetBrains PyCharm Community Edition 3.4 shortcut.
e
b) In the Welcome to Python Community Edition window, select Open Directory.
at

c) In the top-left corner of the Select Path dialog box. select the Home Directory button to select
your user directory.
lic

d) Under your user name, select the triangle next to the Desktop directory to show subdirectories
beneath it.
e) Beneath the Desktop directory, select the triangle next to the AdvPython directory to show
subdirectories beneath it.
up

f) Beneath the AdvPython directory, select the triangle next to the Using Databases directory to show
items beneath it.
g) Beneath the Using Databases directory, select the PizzaCalculator project, and select OK.
D

h) On the left side of the PyCharm window, in the Project window, verify that PizzaCalculator is listed.

2. Create the create-database.py file in the PizzaCalculator project.


ot

a) In the left window, right-click on the PizzaCalculator project name.


b) From the menu, select New →Python file.
c) In the Name text box, type create-database
N

d) Select the OK button to create the file.

3. Create a new database.


o
D

Lesson 3: Using Databases | Topic B


68 | Python® Programming: Advanced

a) Add the statements as shown.


If you would prefer that
you or your students not
type the code in step 3a,
you can copy it from
SNIPPET 1, provided in
Snippets.txt.

e
ut
These statements:
• Import the SQLite3 library.

ib
• Use the connect() method to connect to the database.
• Use the cursor() method to create a cursor object to point to the database connection.

tr
4. Create the toppings and prices tables.

is
a) In create-database.py, write the statements that create the toppings and prices tables.
If you would prefer that
you or your students not

D
type the code in step 4a,
you can copy it from
SNIPPET 2, provided in
Snippets.txt.

5. Insert data into the toppings table.


or
a) In create-database.py, write the statements that insert data into the toppings table.
e
If you would prefer that
at

you or your students not


type the code in step 5a,
you can copy it from
lic

SNIPPET 3, provided in
Snippets.txt.
up
D
ot

These statements:
• Create a tuple value that contains the INSERT statement template for the toppings data.
N

• Create a list of tuple values that contain the data values for the toppings.
• Add an executemany() method to add the toppings data.
o

6. Insert data into the prices table.


D

Lesson 3: Using Databases | Topic B


Python® Programming: Advanced | 69

a) In create-database.py, write the statements that insert data into the prices table.
If you would prefer that
you or your students not
type the code in step 6a,
you can copy it from
SNIPPET 4, provided in
Snippets.txt.

e
ut
ib
These statements:

tr
• Create a tuple value that contains the INSERT statement template for the prices data.
• Create a list of tuple values that contain the product and price data.

is
• Add an executemany() statement to add the prices data.

7. Commit the transactions, and close the database connection.

D
If you would prefer that
you or your students not

or type the code in step 7,


you can copy it from
SNIPPET 5, provided in
Snippets.txt.
e
at

8. Run the create-database script.


a) Run create-database.py.
b) In the Run output window, ensure that the program finishes with an exit code of 0.
lic
up
D
ot
N
o
D

Lesson 3: Using Databases | Topic B


70 | Python® Programming: Advanced

c) In the Project window, observe the new pizza.db database file.

e
ut
ib
Point out that students Unfortunately, you can't open it directly, as it's a binary-formatted file.
will test the database file
in the next activity.

tr
is
D
or
e
at
lic
up
D
ot
N
o
D

Lesson 3: Using Databases | Topic B


Python® Programming: Advanced | 71

ACTIVITY 3-3
Using a Database

Before You Begin

e
The PizzaCalculator project is open in PyCharm. You have created the pizza.db database file.

ut
Activity: Using a
Scenario Database
You will create a price lookup tool that will read the database and populate a table that shows the

ib
pizza sizes, the price of each size, and the price for toppings at each size.

tr
1. Create the look-up-prices.py script in the PizzaCalculator project.

is
a) In the left window, right-click on the PizzaCalculator project name.
b) From the menu, select New→Python file.
c) In the Name text box, type look-up-prices

D
d) Select the OK button to create the file.

2. Create the template code to build a window and import the tkinter and sqlite3 libraries.
a) Add the following code to the look-up-prices.py script.
or If you would prefer that
you or your students not
e
type the code in step 2a,
you can copy it from
at

SNIPPET 6, provided in
Snippets.txt.
lic
up
D
ot
N

These statements:
• Import the tkinter library and the sqlite3 library.
• Define the Application class and the constructor method.
o

• Instantiate the Tk() object, set the window title and size, instantiate the Application class,
and run the mainloop() method.
D

3. In the Application constructor method, add code to read the prices from the pizza.db database file,
and create the widgets method.

Lesson 3: Using Databases | Topic B


72 | Python® Programming: Advanced

a) Add the following code to the look-up-prices.py script.


If you would prefer that
you or your students not
type the code in step 3a,
you can copy it from
SNIPPET 7, provided in
Snippets.txt.

e
ut
ib
tr
is
D
These statements:
• Connect to the database and create the cursor.


or
Create the prices dictionary object—for now, just setting the prices to all 0 values.
Submit a SELECT statement to retrieve the prices from the prices table, placing the values in the
prices dictionary.
Close the database connection using the close() method.
e
• Call the create_widgets() method, which you haven't provided yet.
at

4. Create a form to display the prices values.


a) Add the following code to the look-up-prices.py script after the constructor, but before the code that
lic

instantiates the window.


If you would prefer that
you or your students not
up

type the code in step 4a,


you can copy it from
SNIPPET 8, provided in
Snippets.txt.
D
ot
N
o
D

These statements:
• Create the create_widgets() method.
• Create headings for the table.

Lesson 3: Using Databases | Topic B


Python® Programming: Advanced | 73

b) After the headings, but before the instantiation code, add the following code.
If you would prefer that
you or your students not
type the code in step 4b,
you can copy it from
SNIPPET 9, provided in
Snippets.txt.

e
ut
ib
tr
is
D
or
e
at
lic

These statements:
• Create three rows, one for each pizza size.
• Create three columns, one for the label, one for the pizza size price, and one for the topping size
up

price.
• Create the fields to display the prices for each pizza size and topping.

5. Run the look-up-prices script.


D
ot
N
o
D

Lesson 3: Using Databases | Topic B


74 | Python® Programming: Advanced

a) Run look-up-prices.py.

e
ut
ib
tr
The window shows the base price for each pizza size and the price for each topping at that size.
The prices have been read from the database.

is
D
or
e
at
lic
up
D
ot
N
o
D

Lesson 3: Using Databases | Topic B


Python® Programming: Advanced | 75

TOPIC C
Manipulate SQL Data
Often, for applications that use databases, the SQL required to interact with the data can get more
complicated than the actual Python code that uses the data. It helps to know the basics of SQL to
help with the database interaction.

e
ut
Database Queries
The SQL SELECT statement is used to submit data queries to the SQLite database engine. The Database Queries

ib
database engine processes the query and returns a result set. The result set contains all of the data
records in the table that match the query criteria. The format of the SELECT statement is:

tr
SELECT fields list FROM table WHERE criteria
The WHERE clause is what limits what data records are returned:

is
SELECT product, price FROM prices WHERE price > 1.00
You then submit the query to the database using the execute() method.

D
The execute() method returns the result set generated by the SELECT statement as a list of values.
The list matches the table data field order. You can iterate through the result set using a standard
for statement:
for row in cursor.execute("SELECT product,price FROM prices"):
prices[row[0]] = row[1]
or
e
For each iteration, the product data field value is assigned to the row[0] list variable, and the price
data field value is assigned to the row[1] list variable.
at

Guidelines for Manipulating Database Data


lic

Follow these guidelines when using SQL to manipulate database data.


Insert Data
up

Insert Data
To insert data into a table, write an INSERT statement that provides two pieces of information: the
list of data fields that are updated with values, and the values themselves:
D

INSERT INTO (list) VALUES (values)


• You don’t need to provide a value for all of the data fields in a data record. If any data fields are
left out, those values are NULL by default.
ot

• If you provide data values for all of the data fields, you can omit the data field list from the
INSERT statement. The VALUES clause defines the data values that are assigned to the data fields.
N

Query Data
Query Data
To query data, write a SQL SELECT statement, using the WHERE clause to specify the data you want
o

to look for:
D

SELECT product, price FROM products WHERE price < 10.00


• Modify the query result set by adding additional clauses. The ORDER BY clause tells the database
engine to sort the data in the result set based on a data field:
SELECT product, price FROM products WHERE price < 10.00 ORDER BY product
• Add the ASC or DESC keywords to make the sort in ascending or descending order:

Lesson 3: Using Databases | Topic C


76 | Python® Programming: Advanced

SELECT product, price FROM products WHERE price < 10.00 ORDER BY product
DESC
• For large result sets, page through the data records using the LIMIT clause:
SELECT product, price FROM products WHERE price < 10.00 ORDER BY product
LIMIT 0,5
• Specify where to start by providing an offset in the first value following the LIMIT clause. The
second value specifies the number of data records to return. In this example, you request the first
five data records in the result set. To request the second five, you'd use:

e
SELECT product, price FROM products WHERE price < 10.00 ORDER BY product
LIMIT 5,5

ut
Update and Delete Data
Update and Delete Data

ib
To update and delete data, use the UPDATE statement. The UPDATE statement also uses a WHERE
clause to specify which data records to update:

tr
UPDATE products SET price = 2.00 WHERE product = 'medium pizza'
• The SET clause is only applied to the data records that match the WHERE clause.

is
• If you need to remove any data records from the database, you use the DELETE statement. Just as
with the UPDATE statement, the DELETE statement uses the WHERE clause to specify just which

D
data records to remove:
DELETE FROM products WHERE product = 'medium pizza'
• Be careful with the DELETE statement; without the WHERE clause, all of the data records from the
table will be deleted without asking.
or
e
at
lic
up
D
ot
N
o
D

Lesson 3: Using Databases | Topic C


Python® Programming: Advanced | 77

ACTIVITY 3-4
Changing Data in a Database

Before You Begin

e
The PizzaCalculator project is open in PyCharm. You have created the pizza.db database file and

ut
the look-up-prices.py script.
Activity: Changing Data
Scenario in a Database

ib
You will create a new script to update the prices stored in the pizza.db database file. In look-up-
prices.py, you have already created a table that displays the current pricing scheme. By adding an

tr
Update prices button and some more code to update the database, you can create a new script that
enables the user to update the data. So, you will start by creating a copy of look-up-prices.py.

is
1. Copy the look-up-prices.py file to update-database.py.

D
a) If it is not already open in the PyCharm editor, open the look-up-prices.py file.
b) From the main PyCharm menu bar, select File→Save As.
c) In the Copy dialog box, change the file name to update-database.py then select the OK button.
d)
or
In the PyCharm editor window, ensure that the update-database.py file is open and that it is the
active document to edit.
e
2. Leave the database connection open so you can update the data.
a) Remove the conn.close() method from line 22 in the code.
at
lic
up
D

You won't close the database here, as you'll need to update it later on.
ot

3. Add widgets that will enable the user to submit the update.
N
o
D

Lesson 3: Using Databases | Topic C


78 | Python® Programming: Advanced

a) At the end of the create_widgets() method, but before the window instantiation line, add the
code shown.
If you would prefer that
you or your students not
type the code in step 3a,
you can copy it from
SNIPPET 10, provided
in Snippets.txt.

e
ut
ib
These statements provide:

tr
• A blank row.
• A button to submit the updated data using the self.update method.

is
• An Entry field to display the status.

D
4. Add the update() method to update the prices table with the values from the form field.
a) After the create_widgets() method, but before the window instantiation line, add the following
code.
If you would prefer that
you or your students not
type the code in step 4a,
you can copy it from
or
e
SNIPPET 11, provided
in Snippets.txt.
at
lic

These lines:
up

• Define the update() method.


• Retrieve the data values from the form and place them in the appropriate prices dictionary
elements.
D
ot
N
o
D

Lesson 3: Using Databases | Topic C


Python® Programming: Advanced | 79

b) Following the code you just entered, add the following.


If you would prefer that
you or your students not
type the code in step 4b,
you can copy it from
SNIPPET 12, provided
in Snippets.txt.

e
ut
ib
tr
is
These lines:
• Use a for loop to iterate through the prices dictionary and submit an UPDATE statement for each
dictionary element, updating the corresponding entry in the prices table.

D
• Call the commit() method after the for loop to commit the updates.
• Display the "Updated" message in the self.entry4 Entry box.

5. Run the update-database.py application.


a) Run the update-database.py script.
The window appears with the current database entries.
or
e
b) Change the prices as shown, then select the Update prices button.
at
lic
up
D
ot

The Updated message is displayed.


N

c) To verify the database was changed, select the X at the top-right corner of the window to close the
program, then re-run the program and verify the updated values are there.
d) Close the Python Pizza Prices window to return to PyCharm.
o

e) Close all editor tabs, but leave the PizzaCalculator project loaded in PyCharm.
D

Lesson 3: Using Databases | Topic C


80 | Python® Programming: Advanced

ACTIVITY 3-5
Add a Database to the Python Pizza Application

Before You Begin

e
The PizzaCalculator project is open in PyCharm. You have created the pizza.db database file, the

ut
look-up-prices.py script, and the update-database.py script. You have updated the prices in the
database.
Activity: Add a Database

ib
to the Python Pizza Scenario
Application
You will now enable the Python Pizza Application to read data from the database.

tr
is
1. Copy the ppc.py file to ppc-database.py.
a) Open the ppc.py file in the editor.
b) From the main PyCharm menu bar, select File→Save As.

D
c) In the Copy dialog box, change the file name to ppc-database.py then select the OK button.
d) In the PyCharm editor window, ensure that the ppc-database.py file is open, and that it is the active
document to edit.

or
2. Update the constructor to read the price data from the database.
a) Change the toppings list to an empty list, and define the prices dictionary to all 0 values.
e
at
lic
up
D
ot
N
o
D

Lesson 3: Using Databases | Topic C


Python® Programming: Advanced | 81

b) Following the statements you just revised, add code to connect to the pizza.db database.
If you would prefer that
you or your students not
type the code in step 2b,
you can copy it from
SNIPPET 13, provided
in Snippets.txt.

e
ut
ib
tr
These statements:

is
• Connect to the pizza.db database.
• Create a cursor object.

D
c) Following the code you just entered, add code to query the database for topping and price data.
If you would prefer that
you or your students not

or type the code in step 2c,


you can copy it from
SNIPPET 14, provided
in Snippets.txt.
e
at
lic
up

This code:
• Uses a for statement to execute a SELECT statement to retrieve the toppings table entries and
D

populate the toppings list with the returned results.


• Uses a for statement to execute a SELECT statement to retrieve the prices and update the
prices dictionary with the returned results.
ot

• Closes the database connection.

3. Import the sqlite3 library.


N

a) Add the following import statement above the class declaration.


o
D

Lesson 3: Using Databases | Topic C


82 | Python® Programming: Advanced

4. Run the ppc-database.py application.


a) Run the ppc-database.py script.

e
ut
ib
tr
is
D
or
e
The toppings are now in alphabetical order due to the ORDER BY clause added to the SELECT
at

statement.
b) Select a Large pizza with Pepperoni, and select Calculate Price.
lic

The total is 13.39, based on the current prices in the database.


c) Close the Python Pizza Calculator window.
d) Run the update-database.py program. Change the price values as shown, and select Update prices.
up
D
ot
N
o
D

e) Close the Python Pizza Prices window.

5. Update the prices and view the result in the price calculator.
a) Run the ppc-database.py program.
b) Select a Large pizza with Pepperoni, and select Calculate Price.
The new total is 14.19, based on the updated prices in the database.

Lesson 3: Using Databases | Topic C


Python® Programming: Advanced | 83

c) Close the Python Pizza Calculator window.

6. Clean up the workspace.


a) Select File→Close Project.
The project is closed.
b) Close the PyCharm Community Edition window to exit PyCharm.

e
ut
ib
tr
is
D
or
e
at
lic
up
D
ot
N
o
D

Lesson 3: Using Databases | Topic C


84 | Python® Programming: Advanced

Summary
In this lesson, you used an SQLite database to store, retrieve, and update data that persists between
sessions. You used SQL to create and structure a database, populate it with data values, and perform
queries to retrieve data.
Encourage students to
use the social What sorts of databases will your own Python applications interact with?

e
networking tools A: Answers will vary depending on your requirements, but a wide range of database options exist for
provided on the CHOICE Python developers. Not only are traditional SQL databases an option, but many cloud-based

ut
Course screen to follow database options are now available, including high-performance NoSQL databases that enable you to
up with their peers after
work with massive data sets.
the course is completed

ib
for further discussion Will your own Python applications use data storage options other than databases?
and resources to support
continued learning. A: While databases meet a wide range of needs, other storage options, such as files (XML and JSON, for

tr
example) may be more suitable for some scenarios.

Note: Check your CHOICE Course screen for opportunities to interact with your classmates,

is
peers, and the larger CHOICE online community about the topics covered in this course or
other topics you are interested in. From the Course screen you can also access available

D
resources for a more continuous learning experience.

or
e
at
lic
up
D
ot
N
o
D

Lesson 3: Using Databases |


4 Network Programming

e
Lesson Time: 2 hours, 15 minutes

ut
ib
tr
Lesson Objectives

is
In this lesson, you will:

D
• Define the different ways to transfer data between applications on a network.
• Design a client-server network application.

Lesson Introduction or
e
These days, just about every computer is connected to some type of network—whether it’s
a simple home network or a complex corporate network with dozens of subnetworks.
at

Python® enables you to leverage the network connectivity of your workstations to allow
them to communicate with each other across the network. This lesson shows how to do just
lic

that.
up
D
ot
N
o
D
86 | Python® Programming: Advanced

TOPIC A
Basics of Network Programming
Before you start coding, it helps to have a basic understanding of how devices communicate across a
network, and what things you need to know to maximize your network connectivity.

e
You may want show the
Spotlight presentations Note: To learn more, view the Spotlight presentations from the Spotlight tile on the CHOICE

ut
from the CHOICE course screen.
Course screen or have
students navigate out to

ib
the Course screen and Connectionless vs. Connection-Oriented
watch them as a
supplement to your The Internet Protocol (IP) standard has become the de facto method of sending data on Local Area

tr
instruction. If not, please Networks (LANs). The IP standard defines how data packets are sent from one device to another
remind students to visit across multiple networks. However, by itself, the IP standard doesn’t define just how that data is
the Spotlights for this

is
processed at the application level.
course on their CHOICE
Course screen after For applications to communicate with each other, a finer control of the data is required. Two

D
class for supplemental popular standards have been built on top of the IP standard that define different methods for
information and moving data between network devices.
additional resources.
Connectionless vs.
Connection-Oriented
Item

Transmission Control
Protocol (TCP)
Description
or
TCP defines a detailed protocol for sending data error-free between two
network devices, ensuring that all data that is sent on one end is received
e
intact on the other end.
The receiving device must acknowledge receipt of each byte of data sent
at

by the sending device, and the sending device can’t send more data than
the receiving device can handle. These rules ensure that whatever data is
lic

sent from one device is properly received by the other device.


The downside to this control is reduced speed and throughput of data.
There is a lot of overhead involved with validating every byte of data sent.
up

For data-driven applications, that’s a small price to ensure the integrity of


the data. However, for applications that work in real-time (such as audio
and video streams), this extra overhead will cause issues.
D

User Datagram To avoid the performance issues of TCP, UDP does not track data the
Protocol (UDP) way TCP does. The sending device sends out a packet of data to the
receiving device, and has no idea if the packet made it to the destination,
ot

or if the destination device was able to process it. While this method can
produce lots of dropped packets, it's much faster in transferring data, as
there’s much less overhead. Most real-time audio and video streaming
N

applications can withstand a few dropped packets in the communication.

TCP is described as providing connection-oriented data transfer, whereas UDP provides connectionless
o

data transfer.
D

Client/Server Paradigm
Client/Server Paradigm After you decide on a network protocol to use, you must decide on how the network devices will
use that protocol to communicate with each other. Both network devices in a connection can’t talk
at the same time. One must be listening for incoming data at the same time the other device sends it.

Lesson 4: Network Programming | Topic A


Python® Programming: Advanced | 87

That means the two devices must agree on a protocol to establish when to send data and when to
listen for data. The most popular protocol method used is the client/server paradigm. With this
paradigm, one side of the connection assumes control over the communication channel. The server
side always listens for incoming connections from clients. The client sends a connection request to
the server, and the server must accept it before communication can begin. Once the connection is
established, the client sends a command to the server, and the server processes the command, then
returns any data requested. This method is used in most popular IP protocols, such as Hypertext
Transfer Protocol (HTTP), File Transfer Protocol (FTP), and Simple Mail Transfer Protocol
(SMTP).

e
In most server environments, there are multiple server programs that listen for connections on the

ut
same network interface. The way the physical server knows which incoming packet goes to which
server program is by using ports. A port is a number assigned to each server program listening for
incoming packets. The client must know the unique port number for the server it wants to

ib
communicate with. Each application server is assigned its own unique port number for the physical
server. All standard Internet protocols are assigned well-known port numbers (such as port 80 for
HTTP, port 21 for FTP, or port 25 for SMTP). You shouldn't use an existing well-known port

tr
number for your application, but usually any port number over 1024 is fair game.

is
Guidelines for Basic Network Programming

D
Note: All Guidelines for this lesson are available as checklists from the Checklist tile on the
CHOICE Course screen.

outline how the network programs will communicate: or


Before you start coding your network program, there are some steps that you'll need to take to

• Determine whether to use a connection-oriented (TCP) or a connectionless (UDP) protocol to


Guidelines for Basic
Network Programming
e
transfer data. Most data-oriented applications should use TCP. Applications that transfer real-
time data (such as streaming audio or video) can use UDP.
at

• Determine a port number to assign to the server program.


• Determine a client/server protocol format to use for the application.
lic

• Determine the client commands and server responses.


up
D
ot
N
o
D

Lesson 4: Network Programming | Topic A


88 | Python® Programming: Advanced

ACTIVITY 4-1
Defining an Application Protocol for the Python
Pizza Calculator

e
Scenario

ut
You are going to turn the Python Pizza Calculator into a client-server application. The server will
provide the latest pricing information to each instance of the client application. The server will run

ib
on one computer, and instances of the client will run on other computers that connect to the server
over a LAN. Before you start, you'll need to work out some networking details.
Activity: Defining an

tr
Application Protocol for
the Python Pizza 1. What connection protocol and port will you use for the application?

is
Calculator
A: Since the Python Pizza Calculator needs to accurately send topping and price data across the
Discuss these questions network, TCP is an appropriate choice. Regarding the port, many numbers are available and
with the entire class or

D
appropriate. (In the activity, you'll use port 8000.)
consider dividing
students into teams.
2. You will modify the Python Pizza Calculator to be either the client application or the server application.
Which one should it be?

or
A: Since customers will run the Python Pizza Calculator window, you'll use that as the client device.
You'll create a separate server program to serve the toppings list and prices dictionary values.
The server will listen on TCP port 8000 and the client (the Python Pizza Calculator window) will
e
request a connection to the server program.
at

3. Which application should initiate the connection?


A: The server will remain running, listening for connections. Clients will come and go. After a client
initiates a connection, the server will send a welcome message to the client to identify itself. The
lic

client must be able to read that message.

4. What requests must the server be able respond to?


up

A: In addition to opening to a new connection, the server must be able to provide toppings, prices, or
terminate the connection (exit). The client will send these as text commands to the server. The
server will return data in response to received client commands. If the server receives a topping
command, it will send the toppings list. If the server receives a prices command, it will send the
D

prices dictionary object. Finally, if the server receives an exit command, it will terminate the
connection with the client.
ot
N
o
D

Lesson 4: Network Programming | Topic A


Python® Programming: Advanced | 89

TOPIC B
Create a Client/Server Program
You've planned the functionality of your client-server application. Now, you will use Python's
socket library to provide communication between a client and server application over a network.

e
Python Socket Library

ut
The Python socket library contains methods for both the client and server programs to interface Socket
with the network card and each other. To use the socket library, you’ll need to import it into your The examples covered

ib
Python script: in this course are
import socket intended to provide a
straightforward

tr
The socket library contains lots of different methods to assist you in your network programming. introduction to network
Here are the most common methods that you’ll use. programming in Python.

is
Point out that it is also
Method Description possible to implement
asynchronous

D
accept() Accepts an incoming connection attempt. communication through
the Standard Library,
bind(address) Binds the socket to an address and port. and that third-party
close()

connect(address)
or
Closes an established connection.
Establishes a connection with a server.
Returns the IP address of the specified host name.
modules, such as
twisted matrix, may help
to simplify complex
network communication
e
gethostbyname(host) tasks.
gethostname() Returns the host name of the local system.
at

gethostbyaddr(address) Returns the host name assigned to an IP address.


lic

listen(backlog) Listen for incoming connections and buffers backlog


connections, if necessary.
recv(bufsize) Receives up to bufsize bytes of data from the connection.
up

send(data) Send the specified data through the connection.


socket(family, type, proto) Creates a network socket interface.
D

Server
ot

With so many methods available, at first, it may seem somewhat complex to use the socket library. Server
However, there's a set process for both the server and client sides of the connection, so coding them
is a snap.
N

For the server, you most often use this sequence of methods:
import socket
o

server = socket.socket(socket.AF_NET, socket.SOCK_STREAM)


host = ''
D

port= 8000
server.bind(host, port)
server.listen(5)
The socket() method parameters are somewhat complex, but they’re also somewhat standard. The
first parameter defines the protocol family (AF_NET requests to use IP), and the second parameter
defines the lower-level protocol (SOCK_STREAM is for TCP connections, and SOCK_DGRAM
for UDP).

Lesson 4: Network Programming | Topic B


90 | Python® Programming: Advanced

The bind() method establishes the program’s link to the socket. It requires a tuple value that
represents the host address and port number on which to listen. If you bind to an empty host
address, the server listens on all IP addresses assigned to the system. If you need to listen on only a
specific network interface address, you can specify the specific hostname or IP address for the
interface.
After you bind the socket, you use the listen() method to start listening for client connections.
The program halts at this point, until it receives a connection request from a client. When a
connection attempt is received, you pass it to the accept() method:

e
client, addr = server.accept()
This is somewhat of an odd format. The two variables are required because the accept() method

ut
returns two data values. The first is a handle that identifies the connection to the client, and the
second is the address of the remote client.

ib
After the connection is established, you use the send() and recv() methods to send data with the
client. When the communication is complete, use the close() method to close the connection.

tr
Client

is
Client Once you have a server running, you can start working on the client program. The client side of the
programming is somewhat simpler:

D
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
host = socket.gethostbyname(“localhost”)
port = 8000
s.connect((host, port)) or
The client code uses the gethostbyname() method to find the connection information for the
e
server, based on the server’s hostname. The localhost address points to the same system that the
program is running on.
at

That’s all you need for the client! Once the server accepts the connection, you use the send() and
recv() methods to communicate with the server. When the communication is complete, the client
lic

also needs to use the close() method to close the connection.

Data Transmission
up

Data Transmission There’s a caveat to sending and receiving data across a network connection. Different types of
computer hardware systems use different formats for storing data in memory. Because of that, it can
D

be dangerous to send data as text or numeric values from one system to another on the network. To
solve that problem, the network interface converts all data to network byte order.
However, because of that, the socket send() method can only send bytes. That means the data you
ot

place in the send() method parameter must be in byte format instead of a text or numeric format.
Fortunately, Python provides a function that can convert text to bytes with the str.encode()
method:
N

s.send(str.encode(“This is a test”))
On the receiving end of the connection, the recv() method returns the received data in raw byte
o

format. To make any sense out of the data, your program will need to convert it to text format.
Again, Python comes through with the bytes.decode() method:
D

data = s.recv(1024)
string = bytes.decode(data)
This is all you need to send and receive simple text and numeric data across the network.

Lesson 4: Network Programming | Topic B


Python® Programming: Advanced | 91

Serialization
Often, you’ll have more complex data types (objects, such as lists or dictionaries) that you need to Serialization
send between devices. To do that, you need to incorporate a process called serialization. With
serialization, the complex data type is broken down (serialized) into a text item before being sent on
the network. When the data is received on the other end of the connection, the received data is then
converted back into the original data type.
While this sounds complicated, as with everything else, there are Python methods to help you out.
Currently, the most popular method used to serialize complex data types is the JavaScript Object

e
Notation (JSON) data-interchange format. The json Python library implements methods that use

ut
JSON to serialize complex data types and convert them back into the original data type. The
dumps() method serializes the complex data into a text string, and the load() method converts it
back into the complex data type:

ib
output = str.encode(json.dumps(data))
client.send(output)

tr
data = client.recv(1024)

is
text = json.load(bytes.decode(data))

Guidelines for Handling Data on a Network

D
The json and socket library methods simplify the process of sending complex data between Guidelines for Handling
devices across any type of network: Data on a Network
• Serialize complex data using the json dumps() method.
• Encode the serialized data using the str.encode() method.
or
• Send the encoded data to the remote host using the socket send() method.
e
• On the other end, receive the data using the socket recv() method.
at

• Decode the data using the bytes.decode() method.


• Convert the data back to its original data type using the json loads() method.
lic

Guidelines for Network Security


Remember that when you communicate data over a network, it may be exposed to security threats. Guidelines for Network
up

If you intend to transfer sensitive information, be sure to take measures to secure communications. Security
For example:
• Use the Python Transport Layer Security/Secure Sockets Layer (TLS/SSL) wrapper library
D

(ssl.py) to encrypt messages sent over the communication channel.


• Verify that you are communicating only with those you intend to communicate with. For
example, you could maintain a list of IP addresses that are allowed to connect to the server (a
ot

whitelist), and write the server code to accept connections only from IP addresses in that list.
The server can call socket.getpeername() to determine the client's IP address. Make sure that
the list of acceptable addresses is stored in a secure location that can't be modified by
N

unauthorized users or software processes.


• For security monitoring, use the Python logging module to log network connections and
o

attempts to connect as they occur.


• Don't permit open-ended commands (such as SQL statements, Python commands, or other
D

scripting/programming code) to be transmitted between the client and server as a means of


remote control, as this increases the possibility of illicit instructions being provided to the server.
Use a very limited set of commands to provide messaging between the client and server.

Lesson 4: Network Programming | Topic B


92 | Python® Programming: Advanced

ACTIVITY 4-2
Creating a Server for the Python Pizza
Calculator

e
Data Files

ut
All project files in Desktop\AdvPython\Network Programming\PizzaCalculator
Activity: Creating a

ib
Server for the Python Scenario
Pizza Calculator
You'll create a server program to serve Python Pizza Calculator clients with the current list of

tr
toppings and pizza prices from a central location across the network. The server will use TCP port
8000.

is
1. Launch PyCharm and open the PizzaCalculator project.

D
a) From the desktop, double-click the JetBrains PyCharm Community Edition 3.4 shortcut and select
Open Directory.
b) Navigate to the Desktop\AdvPython\Network Programming directory, select the PizzaCalculator
project, and select OK.
or
c) On the left side of the PyCharm window, in the Project window, verify that PizzaCalculator is listed.

2. Create the ppc-server.py file in the PizzaCalculator project.


e
a) In the left window, right-click on the PizzaCalculator project name.
at

b) From the menu, select New→Python file.


c) In the Name text box, type ppc-server
d) Select the OK button to create the file.
lic

3. Add the required import statements and code to read data from the database.
If you would prefer that a) Add lines to import the libraries that will be used by the server.
up

you or your students not


type the code in steps
3a and 3b, you can copy
it from SNIPPET 1,
D

provided in Snippets.txt.
ot
N
o
D

Lesson 4: Network Programming | Topic B


Python® Programming: Advanced | 93

b) Skip a line after the import statements and add the following statements.

e
ut
ib
tr
is
D
or
e
at

These statements:
• Connect to the pizza.db database using the sqlite3.connect() method (line 7).
• Create a cursor object for the connection (line 8).
lic

• Create an empty toppings list (line 10), then submit the SQL SELECT statement to retrieve the
data from the toppings table and populate the list with the data values (lines 11 and 12).
• Encode the toppings list for network transmission (line 14).
up

• Create the dummy prices dictionary object (lines 15 through 20), then submit the SQL SELECT
statement to retrieve the price data from the prices table and populate the dictionary object with
the data values (lines 22 and 23).
• Encode the prices list for network transmission (line 25).
D

• Close the database connection (line 26).

4. Program the server-side communication.


ot
N
o
D

Lesson 4: Network Programming | Topic B


94 | Python® Programming: Advanced

a) After the code you just entered, add the following.


If you would prefer that
you or your students not
type the code in step 4a,
you can copy it from
SNIPPET 2, provided in
Snippets.txt.

e
ut
ib
These statements:
• Create a socket object on port 8000.

tr
• Bind to all interfaces on the local workstation.
• Listen to incoming connections on TCP port 8000.
b) Create a while loop to listen for connections.

is
If you would prefer that
you or your students not

D
type the code in step 4b,
you can copy it from
SNIPPET 3, provided in
Snippets.txt.
or
e
at
lic

The while loop accepts incoming connections from clients and sends the welcome message. This
will loop continually. Next, you need to add code to listen for various commands, including one to
break out of the loop and close the connection.
up
D
ot
N
o
D

Lesson 4: Network Programming | Topic B


Python® Programming: Advanced | 95

c) Create an inner loop to listen for various commands.


If you would prefer that
you or your students not
type the code in steps 4c
and 4d, you can copy it
from SNIPPET 4,
provided in Snippets.txt.

e
ut
ib
tr
is
D
These statements:
• Continually loop, listening for messages from the client. or
• Send the toppings list if the client sends the toppings command (lines 43 through 45).
e
• Send the prices list if the client sends the prices command (lines 46 through 48).
• Break out of the loop if the client sends the exit command.
at

d) Close the connection when the inner loop is exited.


lic
up
D

This statement, which closes the connection with the client, is reached only when the exit
command causes a break in the inner loop.
ot

5. Run the program and watch the results.


N
o
D

Lesson 4: Network Programming | Topic B


96 | Python® Programming: Advanced

a) Run ppc-server.py.

Note: At some point, you may be prompted by your local firewall service to
allow the application to communicate over the network. If this happens, select
the option to allow it.
In the console window, you will see output from the server. For now, all you'll see is the Listening for
a client output.

e
ut
ib
tr
is
D
6. Stop the server program.
a) In the left side of the console area, select the red square icon to stop the program.
b) Press Ctrl+F4 to close the console.

or
e
at
lic
up
D
ot
N
o
D

Lesson 4: Network Programming | Topic B


Python® Programming: Advanced | 97

ACTIVITY 4-3
Adding Network Features to the Python Pizza
Calculator

e
Before You Begin

ut
The PizzaCalculator project is open in PyCharm.
Activity: Adding Network

ib
Scenario Features to the Python
Pizza Calculator
You're ready to connect the Python Pizza Calculator client application to the server to retrieve the

tr
toppings list and prices dictionary.

is
1. Copy the ppc.py file to ppc-client.py.
a) If it is not already open in the PyCharm editor, open the ppc.py file by double-clicking its entry in the

D
project file list on the left side of the window.
b) From the main PyCharm menu bar, select File→Save As.
c) In the Copy dialog box, change the file name to ppc-client.py and then select the OK button.

document to edit.

2. Add code to obtain pricing information from the server.


or
d) Ensure that the ppc-client.py file is open in the PyCharm editor window, and that it is the active
e
a) Import the socket and json libraries.
at
lic
up

b) Change the toppings list to an empty list, and define the prices dictionary to all 0 values.
D
ot
N
o
D

3. Add code to connect to the ppc-server program and receive the welcome message.

Lesson 4: Network Programming | Topic B


98 | Python® Programming: Advanced

a) After the statement that initializes self.prices, insert a new line and add code to connect to the server
and receive the welcome message.
If you would prefer that
you or your students not
type the code in step 3a,
you can copy it from
SNIPPET 5, provided in
Snippets.txt.

e
ut
ib
tr
is
D
These statements:
• Establish a socket connection on localhost, port 8000.

or
• Receive the welcome message in a buffer variable named data.
b) After the code you just added, add code to send the toppings command to the server, retrieve the
data, and place it in the toppings list object.
e
If you would prefer that
you or your students not
at

type the code in step 3b,


you can copy it from
SNIPPET 6, provided in
lic

Snippets.txt.
up
D
ot

These statements:
• Encode the text "toppings" using the str.encode() method, and send it using the socket
N

send() method.
• Retrieve the result using the socket recv() method.
• Use the bytes.decode() method to convert it into a string value.
o

• Load the JSON format using the json loads() method to create the toppings list.
D

Lesson 4: Network Programming | Topic B


Python® Programming: Advanced | 99

c) After the code you just added, add code to send the prices command to the server, retrieve the
data, and place it in the prices dictionary object.
If you would prefer that
you or your students not
type the code in step 3c,
you can copy it from
SNIPPET 7, provided in
Snippets.txt.

e
ut
ib
tr
is
These statements:

D
• Encode the text "prices" using the str.encode() method, and send it using the socket send()
method.
• Retrieve the result using the socket recv() method.

• or
Use the bytes.decode() method to convert it into a string value.
Load the JSON format using the json loads() method to create the prices dictionary object.

4. After the code you just added, add code to send the exit command to the server.
e
If you would prefer that
at

you or your students not


type the code in step 4,
you can copy it from
lic

SNIPPET 8, provided in
Snippets.txt.
up
D
ot

This closes the connection to the server.

5. Prepare to test the client by first running the server.


N

a) Run the ppc-server.py script.


o
D

Lesson 4: Network Programming | Topic B


100 | Python® Programming: Advanced

b) In the PyCharm window, observe the console output, showing that the server is listening for client
connections.

e
ut
ib
6. Run the ppc-client program.

tr
a) Run the ppc-client.py script.
b) The Python Pizza Calculator window should appear, with the list of toppings. Select a size and some

is
toppings, then select the Calculate Price button.

D
or
e
at
lic
up
D
ot
N

7. In the console window, select the ppc-server tab and view the server output.
o
D

Lesson 4: Network Programming | Topic B


Python® Programming: Advanced | 101

e
ut
ib
8. Clean up the workspace.
a) In the left side of the console area, select the red square icon to stop the server.

tr
b) In the upper-right corner of the client application window, select the X to stop the client program.
c) Select a console window and press Ctrl+F4 twice to close the console windows.

is
d) Select File→Close Project to close the project.
e) Close the PyCharm Community Edition window to exit PyCharm.

D
or
e
at
lic
up
D
ot
N
o
D

Lesson 4: Network Programming | Topic B


102 | Python® Programming: Advanced

Summary
In this lesson, you used the socket library to implement a client-server connection between two
Python applications.
Encourage students to
use the social In your own Python applications, will you have a need to develop client-server applications?
networking tools A: Answers will vary. For some developers, this is a primary reason why they use Python. However you

e
provided on the CHOICE may develop applications that are completely self-contained and require no network connections. In
Course screen to follow other classes, your applications may use cloud services, and you may be more likely to use a library

ut
up with their peers after
other than socket to access web or cloud services.
the course is completed
for further discussion What measures might you need to take if your client-server application transmitted sensitive information?

ib
and resources to support
continued learning. A: The Python Pizza Calculator transmits messages as clear text. If you need to transmit sensitive data,
you should consider adding encryption and decryption capabilities on either end of the message.

tr
Using a protocol such as SSL provides a secure connection that authenticates users on each end of
the communication and encrypts data in the communication channel.

is
Note: Check your CHOICE Course screen for opportunities to interact with your classmates,
peers, and the larger CHOICE online community about the topics covered in this course or

D
other topics you are interested in. From the Course screen you can also access available
resources for a more continuous learning experience.

or
e
at
lic
up
D
ot
N
o
D

Lesson 4: Network Programming |


5 Managing Multiple
Processes with

e
ut
Threading

ib
Lesson Time: 2 hours, 30 minutes

tr
is
D
Lesson Objectives
In this lesson, you will: or
• Run multiple operations concurrently in the same process space.
e
• Manage resources accessible to threaded applications.
at

Lesson Introduction
lic

Today’s computing environment of dual-core and quad-core processors provides the ability
to run multiple processes on a system at the same time, helping increase the performance of
up

your applications. You can take advantage of this power by incorporating threading in your
Python® programs.
D
ot
N
o
D
104 | Python® Programming: Advanced

TOPIC A
Create a Threaded Application
You've created an application that may need to run multiple operations simultaneously. You can
implement this capability through threading.

e
You may want show the
Spotlight presentations Note: To learn more, view the Spotlight presentations from the Spotlight tile on the CHOICE

ut
from the CHOICE course screen.
Course screen or have
students navigate out to

ib
the Course screen and Threading
watch them as a
supplement to your When you run the Python Pizza Calculator server program, you may run into a small problem. If

tr
instruction. If not, please more than one client attempts to query the server at the same time, only one client will be serviced
remind students to visit at a time. That’s because the server program runs as a single process on the system, and can only
the Spotlights for this

is
communicate with one client at a time. In a high-volume multi-user environment, making customers
course on their CHOICE
Course screen after wait in line just won't work. Threading helps solve that problem.

D
class for supplemental Threading enables you to break off separate functions in your program into separate processes
information and running on the system. Instead of the program accepting a client connection and having to wait until
additional resources. the client finishes before accepting another client, your program can use threading to fork the
Threading
client requests.
or
connection to a separate program thread, leaving the original thread available to listen for more

Threading can also be used in programs that require processing of multi-part, complex data. For
example, there may be times when your program needs to calculate several values first, then
e
combine those values into a final calculation. You can fork the calculations into separate threads to
at

run in queued order, then return to the main thread to combine the answers into a final value.
With threading, there's always a main process that initiates the individual threads. A thread is a single
process block on the central processing unit (CPU). Threads that run in the foreground on the
lic

computer system are also called processes, while threads that run in background on the computer
system are called daemons. Daemons can continue to run after the main thread completes. When that
happens, they're called orphans. Orphaned threads can cause problems on a system, so it's best to
up

avoid that situation.

Thread Objects
D

Thread Objects Python uses the threading library to implement threading in your programs. There is an older
Python library named thread, but it has been deprecated and shouldn’t be used. The threading
ot

library includes the Thread class, which allows you to create separate thread objects in your
programs.
To create a thread object, you just create a subclass of the Thread class:
N

from threading import *


class myThread(Thread):
o

def __init__(self):
threading.Thread.__init__(self)
D

The Thread class includes several methods and properties for working with threads.

Feature Description

daemon Thread property that determines whether the thread runs in background or
foreground.

Lesson 5: Managing Multiple Processes with Threading | Topic A


Python® Programming: Advanced | 105

Feature Description
ident Thread property that uniquely identifies each running thread.
is_alive() Method to determine if the thread is active.
join() Method to allow the main thread to wait until a forked thread terminates.
name Thread property that you can assign to identify the thread.
run() Method that is processed when the thread starts.

e
start() Method used to initialize a thread and execute the run() method.

ut
Guidelines for Python Threading

ib
Note: All Guidelines for this lesson are available as checklists from the Checklist tile on the
CHOICE Course screen.

tr
Follow these guidelines when working with threads in your Python programs: Guidelines for Python

is
• Import the threading library. Threading
• Create a subclass of the Thread class.

D
• Define the run() method and place the code you want to run in the thread inside the method.
• In the main program, instantiate an instance of the thread subclass.
• Run the start() method for the subclass to start the thread.

or
e
at
lic
up
D
ot
N
o
D

Lesson 5: Managing Multiple Processes with Threading | Topic A


106 | Python® Programming: Advanced

ACTIVITY 5-1
Creating a Threaded Application

Scenario

e
Before you add threading capabilities to the Python Pizza Calculator, you want to ensure that you

ut
understand how threading works in Python and the implications of adding it to a program. So, you'll
develop a script that will use threads to calculate the factorial of several numbers, using separate
threads for each calculation. You find the factorial of a number by multiplying the series of numbers

ib
from 1 up to the number. For example, the factorial of 5 is 1 * 2 * 3 * 4 * 5. By logging the results in
the console, you'll be able to test whether the calculations are actually being performed in separate
threads.

tr
Activity: Creating a
Threaded Application

is
1. Launch PyCharm and create a new project.
a) From the desktop, double-click the JetBrains PyCharm Community Edition 3.4 shortcut.

D
b) In the PyCharm Community Edition window, select Create New Project.
c) In the Create New Project dialog box, in the Project name text box, type Factorials
d) Next to the Location field, select the Browse button to open the Select Location for Project Directory
dialog box.
or
e) Navigate to the Desktop\AdvPython\Managing Multiple Processes with Threading directory.
f) Select the Managing Multiple Processes with Threading directory, and select OK to return to the
Create New Project dialog box.
e
A new Factorials subdirectory will be created within the Managing Multiple Processes with
at

Threading directory.
g) Select OK to create the new project.
h) On the left side of the PyCharm window, in the Project window, verify that Factorials is listed.
lic

2. Create the thread-factorial.py file in the Factorials project.


a) In the left window, right-click on the Factorials project name.
up

b) From the menu, select New→Python file.


c) In the Name text box, type thread-factorial
d) Select the OK button to create the file.
D

3. Define a class of type Thread.


ot
N
o
D

Lesson 5: Managing Multiple Processes with Threading | Topic A


Python® Programming: Advanced | 107

a) Add the following code to thread-factorial.py to create a Thread subclass and constructor.
If you would prefer that
you or your students not
type the code in step 3a,
you can copy it from
SNIPPET 1, provided in
Snippets.txt.

e
ut
This code:

ib
• Imports the threading library (line 3).
• Defines the myFactorial subclass of the Thread class (line 5).

tr
• Defines the __init__() constructor method. The method takes one parameter—the number to
calculate the factorial.

is
b) Add the factorial function code inside the run() method for the thread subclass.
If you would prefer that
you or your students not

D
type the code in step 3b,
you can copy it from
SNIPPET 2, provided in

or Snippets.txt.
e
The run() method:
at

• Prints a message when the thread starts.


• Uses a for loop to accumulate the factorial value, starting at 1 and working up to the value
passed into it, plus one.
lic

• Prints a message when the thread ends.


c) Create three instances of the myFactorial() subclass and specify different numbers to calculate
the factorial with.
up

If you would prefer that


you or your students not
type the code in step 3c,
D

you can copy it from


SNIPPET 3, provided in
Snippets.txt.
ot

d) Start all three threads.


N

If you would prefer that


you or your students not
type the code in step 3d,
you can copy it from
o

SNIPPET 4, provided in
Snippets.txt.
D

You don't have to start the threads in the order in which you created them. In this example,
thread3 is started before thread2.

4. Run the program.

Lesson 5: Managing Multiple Processes with Threading | Topic A


108 | Python® Programming: Advanced

a) Run thread-factorial.py.

e
ut
ib
tr
The output appears in the console area in the editor window. The output shows that all three threads
ran, but your output may not necessarily be in the same output order that the threads were started.
In the example shown here, thread1 (factorial of 10000) completed last, even though it started first.

is
This verifies that the threads function independently and will take as long as needed to complete
their tasks.

D
or
e
at
lic
up
D
ot
N
o
D

Lesson 5: Managing Multiple Processes with Threading | Topic A


Python® Programming: Advanced | 109

ACTIVITY 5-2
Determining the Current Thread

Before You Begin

e
You have created the Factorials project, which is open in PyCharm.

ut
Activity: Determining the
Scenario Current Thread
The Thread class includes the name and ident properties to help you identify threads. There's also

ib
the current_thread() method which returns those properties of the current thread. You can
change the name property to any value you like to help identify individual threads. In this activity,

tr
you'll create a thread that counts from 1 to 10 with a varying delay. You'll then initiate two threads
with different thread names and delay times. You'll watch as Python processes the code in the two

is
threads.

D
1. Create the thread-name.py file in the Factorials project.
a) In the left window, right-click on the Factorials project name.
b) From the menu, select New→Python file.
c)
d)
In the Name text box, type thread-name
Select the OK button to create the file. or
e
2. Program the myThread class.
a) Enter the following code.
at

If you would prefer that


you or your students not
lic

type the code in step 2a,


you can copy it from
SNIPPET 5, provided in
Snippets.txt.
up
D
ot

This code:
• Imports the threading and time libraries.
N

• Defines the myThread subclass of the Thread class, along with its constructor, which takes two
parameters—a name for the thread, and the delay time.
o
D

Lesson 5: Managing Multiple Processes with Threading | Topic A


110 | Python® Programming: Advanced

b) Write the run() method.


If you would prefer that
you or your students not
type the code in step 2b,
you can copy it from
SNIPPET 6, provided in
Snippets.txt.

e
ut
• Line 13 calls the current_thread() method to display information about the current thread.
• The loop in line 14 iterates a counter from 1 through 10. (The loop ends as soon as it reaches
11, so the steps are not performed for a value of 11.)

ib
• Line 15 prints the thread's name, identity, and counter value.
• Line 16 uses the delay value in the sleep() method to delay each loop iteration in the thread.
• Line 17 shows a message when the loop completes.

tr
c) Write code to instantiate and start the threads.

is
If you would prefer that
you or your students not
type the code in step 2c,

D
you can copy it from
SNIPPET 7, provided in
Snippets.txt.

or
e
at

• Line 19 prints a message to show that the main thread started running.
lic

• Lines 20 and 21 create two instances of the myThread subclass, each with a different name and
delay value.
• Lines 23 and 24 start the threads.
up

• Line 25 prints a message to show that the main thread has completed.

3. Run the script and observe the output log.


D
ot
N
o
D

Lesson 5: Managing Multiple Processes with Threading | Topic A


Python® Programming: Advanced | 111

a) Run thread-name.py.

e
ut
ib
tr
is
D
Note: You may need to scroll or change the height of the output window to see
all of the information logged there.
b) In the output window, observe the following:


The name of each thread is shown as the thread is started.
or
The current_thread() method shows the thread subclass name (myThread), along with the
e
name assigned to each thread, and its ident value.
• Each line of output identifies the thread name that you assigned, and the unique ident value for
at

the thread.
• Because the first thread has a lower delay value, it completes before the second thread.
lic
up
D
ot
N
o
D

Lesson 5: Managing Multiple Processes with Threading | Topic A


112 | Python® Programming: Advanced

TOPIC B
Manage Thread Resources
When working with threads, you must pay close attention to how the threads interact with system
resources. If two threads attempt to access the same resource at the same time, they will cause a
deadlock condition. Your program must be able to control how the individual threads access data

e
and hardware on the system.

ut
Resource Collisions

ib
Resource Collisions A common use for threads is to break up a complex task into multiple pieces. Each piece performs a
specific section of the task, and reports back to the main program when it completes. However,

tr
sometimes, one thread needs to complete its actions before another thread can continue. You need
a way to specify that in your thread code. This process is called synchronization.

is
Python implements synchronization using the locking feature. Locking allows one thread to place a
hold on the processing while it performs a crucial code segment. While the lock is in place, the
operating system blocks any other threads from running. When the thread is finished with the

D
crucial code, it must release the lock to allow other threads to continue.
Python uses the threading.Lock class to provide the locking feature for your threads. To create a

mylock = threading.Lock() or
lock, first you need to create an instance of the Lock class:

Then inside the thread code, when you need to block other threads, use the acquire() method to
e
start the block:
mylock.acquire()
at

The acquire() method attempts to lock the resource. If the resource is already locked by another
thread, by default, the acquire() method returns a False value and your program must try again
lic

later. If you prefer, you can add a True value as a parameter to the acquire() method to force
your program to wait until the resource is unlocked. Once you acquire the lock, you must release it
when your thread is done processing. You do that using the release() method:
up

mylock.release()

Data Corruption
D

Data Corruption When you use threading in your applications, you must be careful when handling variables. When
the operating system starts your main program, it allocates an area of memory to store the program
ot

variables. Any threads that your program spawns also have access to that same memory area. That
means you could have several separate threads trying to access the same memory areas at the same
time, which could cause problems.
N

To help solve that issue, you can declare variables to be local to a thread (called thread local storage).
The Python threading.local class in the threading library allows you to specify an object that
holds the thread local attributes. To create a thread local storage area in your program, just
o

instantiate the local class:


D

localdata = threading.local()
Then, you can create attributes to store any thread local data:
localdata.test = 1
localdata.mylist = [1, 2, 3]
You can store any type of data in thread local storage. Any data that you store in the thread local
object can only be accessed by the thread that created it.

Lesson 5: Managing Multiple Processes with Threading | Topic B


Python® Programming: Advanced | 113

Thread-Safe Data Structures


With all the confusion on shared memory spaces, it can become somewhat tricky trying to share Thread-Safe Data
data values between threads. Fortunately, Python provides an easy way to share data between Structures (2 Slides)
threads. The Queue class provides a thread-safe queue object that threads can push data into and
retrieve data from. The queue library contains the Queue class, which allows us to create a queue
object:
myqueue = queue.Queue()

e
By default, you can place an unlimited number of items in the queue. If you want to limit the
number of objects in the queue, specify that value as a parameter when you instantiate the Queue()

ut
object.
Once you create the queue, you can place objects into the queue using the put() method:

ib
myqueue.put(“Item1”)
To retrieve an object from the queue, use the get() method:

tr
test = myqueue.get()
By default, the queue works as a first-in-first-out (FIFO) queue. The get() method retrieves values

is
in the same order that the put() method places them in the queue. You can also create a last-in-
first-out (LIFO) queue using the LifoQueue class.

D
There are a handful of useful methods that go along with the Queue class. The empty() and full()
methods are great ways to determine whether the queue is empty or full. The qsize() method will
return how many items are in the queue.

or
With queues, the key is for one thread to place items into the queue and another thread can safely
retrieve them. However, if you have to worry about threads trying to place data in the queue at the
same time, you can also use the locking feature to block other threads.
e
Threading vs. Multiprocessing
at

Threading runs multiple blocks of code within a shared process and memory space. To prevent Threading vs.
lic

collisions between threads trying to access the same data simultaneously, threads must be managed Multiprocessing
by the locking process (known as the Global Interpreter Lock, or GIL), which enables only one
thread to access an object at one time.
up

Multiprocessing runs multiple blocks of code within separate processes and memory space. If the
computer has multiple CPU cores, multiprocessing (unlike threading) can take advantage of them,
running separate processes simultaneously on different CPU cores.
Threading can speed up certain tasks, but not other tasks. Some processing tasks are CPU-bound,
D

meaning they are slowed down waiting for processing to be done by the CPU. Others may be input/
output (I/O)-bound, meaning they are slowed down by input and output tasks, such as accessing
files from a disk, network, and so forth. Because threading runs separate blocks of code in the same
ot

process, it can't speed CPU-bound tasks, but it can speed up I/O-bound tasks.
If a processing bottleneck occurs when data is obtained from sources outside of the computer (for
N

example, data to be downloaded from various web servers), then threading is well-suited for the
task, since the majority of the effort performed by the task is in waiting for external processes to
complete. You can add a thread for each additional download and the data can be downloaded
o

simultaneously through the separate threads. One download does not have to wait for another to
complete before it can start.
D

On the other hand, if the separate tasks to be performed are locally performed, CPU-intensive tasks,
then multiprocessing may be the more appropriate choice, and it may produce much faster
performance.
There are some potential drawbacks to using multiprocessing, however. It is more complicated to
safely share data across processes, for example. Also, it takes more time to start up a new process
than to start a new thread.

Lesson 5: Managing Multiple Processes with Threading | Topic B


114 | Python® Programming: Advanced

Guidelines for Managing Thread Resources


Guidelines for Managing There are a few simple guidelines to follow to get the best use out of threads in your programs:
Thread Resources • Use the Lock methods on crucial data processing sections to ensure thread synchronization.
• Use local attributes to store internal variables in threads safely.
• Use queues to safely communicate data between threads.

e
ut
ib
tr
is
D
or
e
at
lic
up
D
ot
N
o
D

Lesson 5: Managing Multiple Processes with Threading | Topic B


Python® Programming: Advanced | 115

ACTIVITY 5-3
Communicating Between Threads

Before You Begin

e
You have created the Factorials project, which is open in PyCharm.

ut
Activity: Communicating
Scenario Between Threads
Now you'd like to explore how threads can safely share data using a queue. The main program will

ib
create a list of numbers that need to be processed by the factorial method. The program will load
the list into a queue object, then create a pool of three separate threads to operate on the list. Each

tr
thread will grab the next number from the queue and process it. When the queue is empty, the main
program will signal the threads that they are done and can exit.

is
1. Create the thread-factorial-pool.py file in the Factorials project.

D
a) In the left window, right-click the Factorials project name.
b) From the menu, select New→Python file.
c) In the Name text box, type thread-factorial-pool
d) Select the OK button to create the file.

2. Import libraries, initialize variables, and define the class.


or
e
a) Add the following code.
If you would prefer that
at

you or your students not


type the code in step 2a,
you can copy it from
lic

SNIPPET 8, provided in
Snippets.txt.
up
D

These lines:
• Import the queue and threading libraries.
ot

• Initialize a list to hold the factorial numbers.


• Initialize a queue object.
• Initialize a variable to act as the flag to terminate the threads.
N
o
D

Lesson 5: Managing Multiple Processes with Threading | Topic B


116 | Python® Programming: Advanced

b) Define the calcThread class.


If you would prefer that
you or your students not
type the code in step 2b,
you can copy it from
SNIPPET 9, provided in
Snippets.txt.

e
• The class is a subclass of Thread.

ut
• The constructor takes two parameters—a name for the thread, and the queue object to retrieve
the data from.
c) Create the run() method for the calcThread subclass.

ib
If you would prefer that
you or your students not

tr
type the code in step 2c,
you can copy it from
SNIPPET 10, provided

is
in Snippets.txt.

D
or
e
at

• Line 17 displays a message that shows the name of the thread that is starting.
• Line 18 creates a thread local storage object.
lic

• Lines 19 through 27 contain a while loop that terminates based on the value of the terminate
variable.
• If the queue is not empty yet (line 20), then the next value is retrieved from the queue and the
factorial for it is calculated.
up

• When the queue is empty, execution breaks out to line 28, which displays a message that shows
the name of thread that is completing.

3. Finish up the script by instantiating and running three instances of the thread you just defined.
D
ot
N
o
D

Lesson 5: Managing Multiple Processes with Threading | Topic B


Python® Programming: Advanced | 117

a) Add the following code.


If you would prefer that
you or your students not
type the code in step 3a,
you can copy it from
SNIPPET 11, provided
in Snippets.txt.

e
ut
ib
tr
is
• Lines 30 through 32 instantiate three instances of the calcThread subclass. Each thread has a
different thread name, and the dataQueue object is passed to each one.

D
• Lines 34 and 35 load the numbers from the list into the dataQueue object.
• Lines 37 through 39 start the three threads in the thread pool.
• Lines 41 and 42 run a tight loop that checks the dataQueue object. The loop will be exited when


the data queue is empty.
or
When the queue is empty, line 43 sets the terminate variable to True to signal the threads to
exit.
e
• Line 44 displays a message to show that the main thread is finished.
at

4. Run the thread-factorial-pool application.


a) Run thread-factorial-pool.py.
lic
up
D
ot
N
o
D

Note: Depending on your processor speed and timing of the threads, your
output may not exactly match the output shown here.
b) Determine if all three threads in the thread pool have started.

Lesson 5: Managing Multiple Processes with Threading | Topic B


118 | Python® Programming: Advanced

Depending on how many data values you placed in the queue, and how large the values are, some
threads in the pool may not get used.
c) Examine the console and verify that all threads have exited when the main thread exited.
d) Run the script again, and observe that different threads may process the values, depending on
timing.

5. Close the Factorials project.


a) Select File→Close Project.
PyCharm returns to the Welcome window.

e
ut
ib
tr
is
D
or
e
at
lic
up
D
ot
N
o
D

Lesson 5: Managing Multiple Processes with Threading | Topic B


Python® Programming: Advanced | 119

ACTIVITY 5-4
Using the Threaded Python Pizza Server

Data Files

e
All project files in Desktop\AdvPython\Managing Multiple Processes with Threading

ut
\PizzaCalculator
Activity: Using the
Before You Begin Threaded Python Pizza

ib
Server
PyCharm is running.

tr
Scenario
Now that you've seen how threading works, you will examine a version of the ppc-server.py

is
program in which threading has already been incorporated. After a client connects to the server, a
separate thread is used to process the communication with the client, so the main thread can go

D
back to listening for more clients.

1. Open the PizzaCalculator project.

or
a) In PyCharm, select Open Directory. Navigate to the Desktop\AdvPython\Managing Multiple
Processes with Threading directory, select the PizzaCalculator project, and select OK to open the
project.
e
b) On the left side of the PyCharm window, in the Project window, verify that PizzaCalculator is listed.
at

2. Examine the ppc-threaded-server.py file.


a) In the Project window, open ppc-threaded-server.py.
lic

b) Examine the libraries used by the script.


up
D
ot

The socket, json, sqlite3, and threading libraries are imported.


N
o
D

Lesson 5: Managing Multiple Processes with Threading | Topic B


120 | Python® Programming: Advanced

c) Examine the clientThread class declaration and constructor.

e
ut
ib
tr
is
D
or
• The class is a subclass of the Threading class.
• The client and address are provided as parameters of the constructor.
e
• Data is read from the database in the same manner as it was read in ppc-server.py.
d) Examine the run() method.
at
lic
up
D
ot
N
o
D

The run() method handles client communication in same manner as it was done in ppc-server.py.

Lesson 5: Managing Multiple Processes with Threading | Topic B


Python® Programming: Advanced | 121

e) Examine the code that creates the server socket.

e
ut
ib
• Code to create the server socket is very similar to the code used in ppc-server.py.

tr
• A while loop listens for new client connections, spawning them off to a new clientThread
object in lines 65 and 66, and then continuing to listen for new clients.

is
3. Run the ppc-threaded-server.py program.

D
a) Run ppc-threaded-server.py.
b) Look at the console output to ensure the server is listening for new client connections.

or
e
at
lic
up

4. With the server running, start the ppc-client.py program.


a) Run ppc-client.py.
b) Ensure the Python Pizza Calculator window appears with the toppings.
D

5. In the console, select the tab to observe the ppc-threaded-server console output.
ot
N
o
D

Lesson 5: Managing Multiple Processes with Threading | Topic B


122 | Python® Programming: Advanced

e
ut
ib
tr
The server accepted the client connection, but then started listening for more clients before

is
communicating with the connected client.

6. Close the console windows and disconnect the processes.

D
a) Right-click the ppc-client console window tab, and select Close All.

or
e
at
lic

b) Select Disconnect to disconnect the server.


up
D
ot

c) Select Disconnect to disconnect the client.


N

7. Clean up the workspace.


a) Select File→Close Project.
o

b) Close the PyCharm window.


D

Lesson 5: Managing Multiple Processes with Threading | Topic B


Python® Programming: Advanced | 123

Summary
In this lesson, you used threading to create parallel code threads in your programs.
Encourage students to
In your own applications, will you have a need to implement threading? use the social
A: Answers will vary. In Python, threading is helpful for situations calling for input and output, such as networking tools
downloading and processing web data, or managing network communications. Because of the way provided on the CHOICE
Course screen to follow

e
threading is implemented in Python, some tasks that would benefit from parallel processing, such as
up with their peers after
heavy number-crunching, may actually run slower in threaded applications. Python provides a

ut
the course is completed
multiprocessing module, which is more suitable for running tasks that require true parallel
for further discussion
processing. and resources to support

ib
continued learning.
When implementing threading, are there any factors you'll need to be careful of?
A: One concern that was covered in this lesson is data corruption. When multiple threads access the

tr
same data, it must be accessed in a controlled way.

Note: Check your CHOICE Course screen for opportunities to interact with your classmates,

is
peers, and the larger CHOICE online community about the topics covered in this course or
other topics you are interested in. From the Course screen you can also access available

D
resources for a more continuous learning experience.

or
e
at
lic
up
D
ot
N
o
D

Lesson 5: Managing Multiple Processes with Threading |


D
o
N
ot
D
up
lic
at
e
or
D
is
tr
ib
ut
e
6 Implementing Unit
Testing

e
ut
Lesson Time: 2 hours, 20 minutes

ib
tr
is
Lesson Objectives

D
In this lesson, you will:

• Write and run a unit test case.


• Create a test suite.
or
• Identify the benefits of test-driven development.
e
at

Lesson Introduction
lic

Before you release your Python® application to customers, you'll want to ensure that it's
bug-free. The Python Unit Test feature allows you to create a test environment that ensures
your program works as advertised. However, you can also use the unit test feature to set up
up

a test environment before you even write any code for your application. That allows you to
develop the code to match the test environment, ensuring success in the final product.
D
ot
N
o
D
126 | Python® Programming: Advanced

TOPIC A
Test-Driven Development
Test driven development allows you to create a series of tests that define how the application should
behave before you write any code for the application. Once you define the tests, you then write the
code to pass the tests.

e
You may want show the

ut
Spotlight presentations Note: To learn more, view the Spotlight presentations from the Spotlight tile on the CHOICE
from the CHOICE course screen.
Course screen or have

ib
students navigate out to
the Course screen and Plan for TDD
watch them as a

tr
supplement to your There's nothing worse that working with an application that doesn't work quite right. Being in the
instruction. If not, please middle of an application that produces wrong data, freezes when an event is selected, or

is
remind students to visit unexpectedly crashes creates distrust in your customers, and can lead them to look for an alternative
the Spotlights for this
application. Your goal as a Python developer should be to release error-free applications at all times.
course on their CHOICE

D
Course screen after However, often with short development cycles and multi-member programming teams, trying to
class for supplemental coordinate perfect code can be impossible. One small change made to a minor function can have
information and hidden side-effects in other places in the application, often written by a different team of
additional resources.
TDD
programmers.
or
Test-driven development (TDD) is a programming paradigm that attempts to minimize errors and bugs
in applications. TDD provides a framework that all developers can use to write better, more precise
code in their applications.
e
With TDD, before you write any code, you write a series of specifications (or rules) for each
at

function used in the application. The specifications define how each function works, what data it
requires, how it handles the data, and what data it produces. Consider all aspects of quality as you
write your unit tests. For example, you might include security tests to test for potential
lic

vulnerabilities you have identified. After you write the specifications, identify a series of tests that
can verify whether the code matches each specification.
Once you have designed the tests, write each function to pass the tests. A function isn't released
up

until it can pass all of the tests, ensuring that it meets all of the design specifications. By placing the
code testing at the beginning of the development cycle instead of the end, you ensure all code
matches the design specifications.
D

TDD Benefits
ot

TDD Benefits Creating a series of tests for each function within an application up-front may seem somewhat
unorthodox, but there are benefits to that process. First, by forcing developers to decide on the
specification rules first, you're forcing them to think outside of the box. Trying to determine just
N

how a function could break goes a long way in identifying problems before customers do. This
ensures that each function in an application works as expected, no matter what strange thing an
unwitting customer may throw at it.
o

Also, by writing the specification rules up-front, you ensure that all code changes made during the
D

development cycle don't break the function, or any other functions that rely on the function being
changed.
A side benefit to TDD is that it forces developers to take a modular approach to writing
applications. Instead of cramming all of the features of an application into one monolithic block of
code, TDD forces developers to split functions into separate modules. Each module provides a
separate function of the application and is defined by a separate set of specification rules. Modular
code helps the development process by not only making the application easier to manage, but also

Lesson 6: Implementing Unit Testing | Topic A


Python® Programming: Advanced | 127

can aid in code sharing between applications. Modules that are common between applications can
be shared.
Finally, in large programming shops, TDD helps ensure all of the developers are working off of the
same design goals. Specification rules are written to ensure proper interoperability between
functions in the application. As long as developers write to satisfy the specification rules, the
chances that changes to one function have a negative impact on another function are minimized.
Separate development teams can work on their set of functions knowing just what to expect from
other functions contained in the application.

e
Unit Testing Framework

ut
Tests are divided into three different groups: Unit Testing Framework
(2 Slides)

ib
• Unit tests—test individual functions in an application.
• Integration tests—test how separate functions interact with one another.
• Functionality tests—test how the entire application works as a whole.

tr
The simplest building block for TDD is the unit test. A unit test defines the rules required to test a

is
single unit in the application, usually a function. Each function in an application has its own unit test
rules. They define how the function should operate independent of the rest of the application.
Python has a few different libraries that provide unit test features. Currently, the most popular one

D
is the PyUnit package. The PyUnit package contains classes and methods for performing a series of
unit tests on just about any type of function. It is installed as part of the standard Python library as
the unittest library.

supporting four different unit test features:


or
The core of the unittest library is the TestCase class. The TestCase class provides methods for

• Test fixtures—include code to prepare the test environment for the test, such as setting up data
e
and releasing connections.
at

• Test cases—the code used to test the specification rules against the function.
• Test suite—a collection of multiple test cases that are run together.
• Test runner—the code used to run the unit tests against the function.
lic

The TestCase class defines separate methods for each unit test. Each method name must begin
with the name test. The method contains code that defines the parameters of the test rules.
up

Assertions
The TestCase class checks rules by using assertions. An assertion is a check to determine if a rule Assertions
D

passes or fails. This is often done by testing data values, or whether or not a function exits properly
without any errors. There are several different types of assertions that the TestCase class supports.
ot

Assertion Description

assertEqual(x, y) Checks that x is equal to y.


N

assertNotEqual(x, y) Checks that x is not equal to y.


assertTrue(x) Checks that the value of x is True.
o

assertFalse(x) Checks that the value of x is False.


D

assertIs(x, y) Checks if x is the same type of object as y.


assertIsNot(x, y) Checks if x is not the same type of object as y.
assertIsNone(x) Checks if x is the None value.
assertIsNotNone(x) Checks that x is not the None value.
assertIn(x, y) Checks that x is in y.

Lesson 6: Implementing Unit Testing | Topic A


128 | Python® Programming: Advanced

Assertion Description
assertNotIn(x, y) Checks that x is not in y.
assertIsInstance(x, y) Checks if x is an instance of y.
assertNotIsInstance(x,y) Checks that x is not an instance of y.

A typical unit test class would looks like this:


class myTest(unittest.TestCase):

e
def test_foo(self):

ut
self.assertEqual(foo(10), 100)
This example tests that the output from the foo() function, if sent the value of 10, is 100. If the
returned value is not 100, the assertEqual fails, and the myTest test fails.

ib
Guidelines for TDD

tr
Note: All Guidelines for this lesson are available as checklists from the Checklist tile on the

is
CHOICE Course screen.

Follow these guidelines when planning for TDD.

D
Test Your Code

Test Your Code

develop your testing code:


or
Develop your testing code as you develop the application functionality that it will test. As you

• Direct each testing unit toward testing one small piece of functionality to prove that it works
correctly.
e
• Design each testing unit so it can run alone, as well as within the test suite, in any sequence. This
at

may mean initializing each test with a fresh dataset and performing cleanup afterwards. (You can
write setUp() and tearDown() methods to accomplish this.)
• Strive to write tests that run quickly, so they won't slow down development.
lic

• Run individual testing units frequently as you develop, and run the full suite before and after a
programming session.
up

Develop Each
Application Function Develop Each Application Function
To develop each application function:
D

• Write the requirements for the function.


• Write a series of rules that test each requirement.
• Create the unit test that defines assertions for each rule.
ot

• Develop the function code and run the unit test against it.
• Rewrite any function code that fails a unit test.
N
o
D

Lesson 6: Implementing Unit Testing | Topic A


Python® Programming: Advanced | 129

ACTIVITY 6-1
Planning for TDD

Scenario

e
You have been tasked to write a function that calculates factorials for a larger application. Your

ut
function must follow the standard math rules for factorials. It will receive a single parameter for the
input number, and should return a single number as the factorial if it succeeds, or return a False
value if it fails.

ib
Activity: Planning for
TDD
1. In a sentence or two, define what a factorial is.

tr
A: The mathematical definition for the factorial of a positive integer value is the multiplication of all the
previous integer values up to that value. Thus, the factorial of 5 is 1 * 2 * 3 * 4 * 5 = 120.

is
2. What results should be produced for special numbers and extremes. For example, what is the factorial

D
of 0? What is the factorial of a negative number?
A: The mathematical definition of the factorial of 0 is 1. There is no mathematical definition for the
factorial of a negative number. Our function will return a failure condition if the calling program
supplies a negative value.

or
3. What test cases might you use to test for various normal numbers and special numbers?
A: You might test that various positive numbers return the correct factorial value—perhaps a small,
e
medium, and large value. For example, if our test submits the value of 5 (a small number), the
factorial() function must return a value of 120. It should also ensure that submitting a value of
at

0 returns a value of 1. It should also ensure that submitting a negative value returns a False
value. While not a requirement, the factorial() function must also be able to detect if a non-
numeric value is submitted. If it detects a non-numeric value, it should also return a False value.
lic

These can serve as the basis for your tests.


up
D
ot
N
o
D

Lesson 6: Implementing Unit Testing | Topic A


130 | Python® Programming: Advanced

TOPIC B
Write and Run a Unit Test Case
Once you have determined the rules required for your tests, you're ready to start coding the
TestCase.

e
Unit Test Case

ut
Unit Test Case The TestCase class for the factorial() function will consist of separate assertion tests for each
rule that must be matched. The first method must define a test to check for a valid factorial value:

ib
def test_factorial_valid(self):
self.assertEqual(factorial(5), 120)

tr
The second test method in the TestCase must test that the factorial() function returns a value
of 1 for the factorial of 0:

is
def test_factorial_zero(self):
self.assertEqual(factorial(0), 1)

D
The third method tests that the factorial() function returns a False value if you try to find the
factorial of a negative number:
def test_factorial_negative(self):
self.assertFalse(factorial(-1))
or
Finally, the fourth method tests that the factorial() function returns a False value if you submit
a text value as the parameter:
e
def test_factorial_text(self):
at

self.assertFalse(factorial("text"))
With these four tests, you're ready to code the TestCase for the factorial() function.
lic

Guidelines for Writing a Unit Test


up

Guidelines for Writing a Here are some guidelines to follow when designing tests for a unit test:
Unit Test • Determine the rules that define the function that's being tested.
• Create a TestCase class that contains the separate tests.
D

• Define separate methods for each rule.


• Determine whether a rule must match a returned value, or a True or False Boolean value.
• Run the unittest.main() function to start the tests.
ot
N
o
D

Lesson 6: Implementing Unit Testing | Topic B


Python® Programming: Advanced | 131

ACTIVITY 6-2
Writing a Unit Test

Data Files

e
All project files in Desktop\AdvPython\Implementing Unit Testing\Factorials

ut
Activity: Writing a Unit
Scenario Test
You will build the test case file to test a factorial() function. The PyCharm editor can

ib
automatically generate a unittest stub for you to build on. You'll create the factorial() function
first, then use PyCharm to start the unittest file for you. You will write methods to test for each

tr
of the cases you planned.

is
1. Launch PyCharm and open the Factorials project.
a) From the desktop, double-click the JetBrains PyCharm Community Edition 3.4 shortcut and select

D
Open Directory.
b) Navigate to the Desktop\AdvPython\Implementing Unit Testing directory, select the Factorials
project, and select OK.

2. Create the factorials.py file in the Factorials project.


a) In the left window, right-click on the Factorials project name.
or
c) On the left side of the PyCharm window, in the Project window, verify that Factorials is listed.
e
b) From the menu, select New→Python file.
at

c) In the Name text box, type factorials


d) Select the OK button to create the file.
lic

3. Define the factorial() function and the code to calculate the factorial of a number.
a) Define the factorial() function.
If you would prefer that
up

you or your students not


type the code in step 3a,
you can copy it from
SNIPPET 1, provided in
D

Snippets.txt.
ot
N
o

4. Using PyCharm, generate the test_factorial unittest file.


D

Lesson 6: Implementing Unit Testing | Topic B


132 | Python® Programming: Advanced

a) In the def line, right-click the factorial keyword and select Go To→Test.

e
ut
ib
tr
is
D
or
You are prompted to choose the test for factorial. No tests exist yet, but you are provided with an
e
option to create one.
at
lic

b) Press Enter to accept the Create New Test option.


up
D
ot
N
o
D

The Create test dialog box is shown. Default names for the test file and test class are provided.

Lesson 6: Implementing Unit Testing | Topic B


Python® Programming: Advanced | 133

c) In the Create test dialog box, select the check box to generate the test_factorial test method, and
select the OK button to generate the test file.

e
ut
ib
A new test_factorial.py script is created.

tr
5. In the test_factorial.py script, add methods required to test the factorial() function.

is
a) Import the factorial() function from the factorials library file.

D
or
e
at

b) Remove the test_factorial() method generated by PyCharm.


c) After the TestFactorial class definition, add the methods for the test rules.
lic

If you would prefer that


you or your students not
type the code in step 5c,
you can copy it from
up

SNIPPET 2, provided in
Snippets.txt.
D
ot
N
o
D

Lesson 6: Implementing Unit Testing | Topic B


134 | Python® Programming: Advanced

ACTIVITY 6-3
Running a Unit Test

Before You Begin

e
You have opened the Factorials project in PyCharm, and have added test cases in

ut
test_factorial.py.
Activity: Running a Unit
Test Scenario

ib
Now that you have the test code prepared, you can run the tests and observe the results. If any test
fails, you will have to modify the factorial() function code.

tr
is
1. Perform the unit tests in the test_factorial.py file.
a) Run Unitests in test_factorial.py.

D
or
e
at
lic

The unittest feature in PyCharm runs the unit tests in a special output window in the console
area.
up

b) In the left pane, examine the status of each of the unit tests you defined.
The unit tests show that one test failed . The test_factorial_text test determined if the
factorial() function rejected text as the input. The current factorial() function failed that
D

test.

2. Modify the factorial() function to add a check for text input values.
ot

a) In factorials.py, after the def statement in line 3, add a new line.


N
o
D

Lesson 6: Implementing Unit Testing | Topic B


Python® Programming: Advanced | 135

b) Modify the code as shown.


Change the if clause to an elif, and insert a new if clause before it.

e
ut
ib
tr
is
The new if statement checks whether the number variable contains a number using the
isinstance() method and the Number attribute of the numbers class. This additional check

D
requires the numbers library.
c) Add the import statement to import the numbers library.

or
e
at
lic
up

3. Re-run Unitests in test_factorial.py.


You should now see that all tests passed.
D
ot
N
o

4. Close the project, but remain in PyCharm.


D

a) Select File→Close Project.

Lesson 6: Implementing Unit Testing | Topic B


136 | Python® Programming: Advanced

TOPIC C
Create a Test Suite
While unit tests are useful, usually, an application contains more than just one function. Fortunately,
Python also supports test suites, which enable you to perform multiple unit tests in a single test
environment.

e
ut
Unit Test Suite
Unit Test Suite Single unit tests are great for testing individual functions, but the typical Python application consists

ib
of several functions. It can be somewhat tedious creating separate unit tests for all of the functions
contained in the application. The unittest library also provides a test suite feature that allows you

tr
to group multiple unit tests into a single test group. That allows you to run the test group as a single
test and view the results.

is
The PyCharm editor provides an easy way to create test suites from classes instead of individual
functions. Just right-click on the class name in the class definition and generate the test. The
PyCharm wizard automatically detects the methods defined in the class, and offers you the option to

D
generate tests for each method.

Test as You Develop


Guidelines for Creating a Test Suite
or
Follow these guidelines when developing a test suite for an entire application.
e
Test as You Develop
at

Develop your testing code as you develop the application functionality that it will test:
• Group all of the methods into a single class object.
lic

• Right-click the class name in the class definition.


• From the menu, select the Go To→Test entries.
• Create a new test file.
up

• Select the methods that you need to test from the class methods.
• Customize the test methods to meet the rules defined for your requirements.
Testing Best Practices
D

Follow Testing Best Practices


To follow best practices for testing in Python:
ot

• Direct each testing unit toward testing one piece of functionality to prove it works correctly.
• Design each testing unit so it can run alone, as well as within the test suite, in any sequence. This
may mean initializing each test with a fresh dataset, and performing cleanup afterwards. (You can
N

write setUp() and tearDown() methods to accomplish this.)


• Strive to write tests that run quickly, so they won't slow down development.
• When you find a bug, write a test that exposes the bug, and leave it in the suite after you resolve
o

the bug. Tests accumulated over time will help you and other developers identify potential
problem areas, and will help to ensure that past problems don't reappear.
D

• Give your testing functions long, descriptive names. These are displayed when a test fails, so
descriptive names will be more useful. They will not be called explicitly, so you don't have to be
concerned about them cluttering your code.
• Run individual testing units frequently as you develop corresponding units of functionality.
• Run the full suite before and after each programming session.
• Run the full suite before pushing code to a shared repository.

Lesson 6: Implementing Unit Testing | Topic C


Python® Programming: Advanced | 137

ACTIVITY 6-4
Creating a Test Suite for Python Pizza
Calculator

e
Data Files

ut
All project files in Desktop\AdvPython\Implementing Unit Testing\PizzaCalculator

Before You Begin

ib
PyCharm is running, and the Welcome screen is showing.

tr
Activity: Creating a Test
Scenario Suite for Python Pizza
Calculator

is
You want to test a new script you've created in the Python Pizza Calculator project. The
getPPCData.py file contains two methods that retrieve the toppings and prices inside the main
program. You will create a test suite to check these methods.

D
1. Open the PizzaCalculator project.
a) In PyCharm, select Open Directory.
or
b) Navigate to the Desktop\AdvPython\Implementing Unit Testing directory, select the PizzaCalculator
project, and select OK.
e
c) On the left side of the PyCharm window, in the Project window, verify that PizzaCalculator is listed.
at

2. Examine the getPPCData.py script.


a) In the Project window, open the getPPCData.py file.
lic
up
D
ot
N
o
D

Lesson 6: Implementing Unit Testing | Topic C


138 | Python® Programming: Advanced

b) Examine the methods in the GetPPCData class.

e
ut
ib
tr
is
D
or
e
at
lic

The get_toppings() and get_prices() methods read data from the local database file and
up

return toppings and prices data.

3. Use PyCharm to generate the test suite for both of the methods contained in the GetPPCData class.
D
ot
N
o
D

Lesson 6: Implementing Unit Testing | Topic C


Python® Programming: Advanced | 139

a) In line 6, right-click on the GetPPCData keyword and select Go To→Test.

e
ut
ib
tr
is
b) In the Choose test for GetPPCData dialog box, press Enter to display the Create test dialog box.

D
c) In the Create test dialog box, select the check boxes to generate the test_get_toppings and
test_get_prices methods, and select OK.

or
e
at
lic
up
D

The test_getPPCData.py file is created.


ot

4. Modify the default test suite to add tests for the get_toppings() and get_prices() methods.
N
o
D

Lesson 6: Implementing Unit Testing | Topic C


140 | Python® Programming: Advanced

a) Import the GetPPCData class from the getPPCData library file.

e
ut
ib
b) On line 9, revise the self.fail() statement for the test_get_toppings() test as shown.

tr
is
D
This checks if the length of the toppings list returned matches the number of toppings you have in
the toppings table.

or
c) On line 12, revise the self.fail() statement for the test_get_prices() test as shown.
e
at
lic
up
D
ot
N
o
D

Lesson 6: Implementing Unit Testing | Topic C


Python® Programming: Advanced | 141

ACTIVITY 6-5
Running a Test Suite

Before You Begin

e
You have created the test suite for the PizzaCalculator project, which is open in PyCharm.

ut
Activity: Running a Test
Scenario Suite
You will run the test suite you built for the GetPPCData class methods to determine if the code you

ib
created passes the tests.

tr
1. Run the test_getPPCData.py test suite file.

is
a) Run ppc-server.py.
When the server runs, it displays the "Listening for a client" message in the console.

D
b) Run Unittests in test_getPPCData.py.
c) Observe the unit test output in the console window. Both tests should have completed successfully. Toggle using soft wraps
in the current editor;

or otherwise, the full output


doesn't display and the
user won't see true
unless they go to the
end manually.
e
at
lic

2. Clean up the workspace.


a) Select File→Close Project.
b) Select Disconnect from the server process.
up

c) Close the PyCharm window.


D
ot
N
o
D

Lesson 6: Implementing Unit Testing | Topic C


142 | Python® Programming: Advanced

Summary
In this lesson, you used Python's unit testing capabilities to test your Python applications.
Encourage students to
use the social Will you use unit testing in your own applications?
networking tools A: Some developers view the writing of test functions as additional, unnecessary programming overhead.
provided on the CHOICE Many developers, however, find that unit testing helps them produce robust code. Many believe that
Course screen to follow

e
the process of designing test cases and writing modular code (driven by unit testing) enforces a
up with their peers after
discipline that leads to better applications. With experience, many developers find they can write code

ut
the course is completed
more quickly when they are using unit testing because of the problems they avoid.
for further discussion
and resources to support How will your own development projects benefit from automated unit testing?

ib
continued learning.
A: Answers will vary. TDD enables you to make significant changes to code and relatively quickly
determine if those changes have inadvertently affected the functionality of the program. They can

tr
help you and other team members avoid producing inadvertent side effects or bugs, especially in
large, complex projects, or projects in which multiple developers are working.

is
Note: Check your CHOICE Course screen for opportunities to interact with your classmates,
peers, and the larger CHOICE online community about the topics covered in this course or

D
other topics you are interested in. From the Course screen you can also access available
resources for a more continuous learning experience.

or
e
at
lic
up
D
ot
N
o
D

Lesson 6: Implementing Unit Testing |


7 Packaging an Application
for Distribution

e
ut
Lesson Time: 2 hours, 10 minutes

ib
tr
is
Lesson Objectives

D
In this lesson, you will:

• Add all items to the package. or


• Create a minimal structure for the application.

• Generate a Windows executable from a Python app.


e
at

Lesson Introduction
lic

Once you've created an application, you may want to think about sharing it with the world.
The default Python® installation includes utilities to help you bundle all of the files required
for your application into one place for easy distribution.
up
D
ot
N
o
D
144 | Python® Programming: Advanced

TOPIC A
Create a Package Structure
Python packages rely on a standard structure so installation programs can easily install them in any
Python installation environment.

e
You may want show the
Spotlight presentations Note: To learn more, view the Spotlight presentations from the Spotlight tile on the CHOICE

ut
from the CHOICE course screen.
Course screen or have
students navigate out to

ib
the Course screen and Package Name
watch them as a
supplement to your Now that you have a completed Python application, you may want to think about distributing it to

tr
instruction. If not, please others. Even if you don't want to share your Python application with others, you may still need to
remind students to visit install your application on multiple computers. Either way, you'll want to bundle all of the files in
the Spotlights for this

is
your application into a Python package.
course on their CHOICE
Course screen after A Python package is a standard way of bundling all of the program, data, and test files required for

D
class for supplemental an application into a single manageable folder. That folder can then be bundled for distribution
information and using any type of distribution means, such as zip files, Linux® package management tools, or the
additional resources. Windows® installer tool.
Package Name

or
Before you start packaging your Python application, though, you'll need to spend a few minutes
thinking about your package name. Because Python packages can be installed anywhere, you should
try to make your Python package name unique. You can't install two packages with the same name
in your Python environment.
e
at

PyPI
You'll also need to consider how you will distribute your packages to other users, as this will
lic

PyPI
determine what kind of package you need to create. A common means of distribution is the Python
Package Index (PyPI)) website at http://pypi.org, which is a central clearinghouse for shared Python
applications and code. When you distribute a package through PyPI, other users can download and
up

install your package to their own computer.


For example, in PyCharm, you can directly install a package from PyPI using the Settings dialog
box's Project Interpreter. When you select the Install button (shown as a + on the right side of
D

the Project Interpreter dialog box), a searchable list of available packages is shown. You simply
select a package and select the Install Package button to download and add the package to your
Python installation. Other Python programming tools and operating systems provide other
ot

convenient ways to install packages directly from PyPI.


N
o
D

Lesson 7: Packaging an Application for Distribution | Topic A


Python® Programming: Advanced | 145

e
ut
ib
tr
is
D
Figure 7-1: Selecting a package to download from PyPI.

or
Note: Even if you don't plan on distributing your application world-wide, it's always a good idea
to check out the package names in PyPI so that your package won't conflict with any other
e
popular Python package that may be installed on your system.
at

Pip Install
lic

You can download and install packages directly within PyCharm by using the Project Interpreter. Pip Install
But there may be times when you prefer to use the command line. To install packages, you can use
the pip install command.
up

You can use pip install to install packages from PyPI or another repository, as well as from
packages in a local package archive (a TAR or ZIP file) that you have already downloaded and have
in a local file.
D

Note: When you work with Python from the command line, to ensure that Python commands
such as pip install are found, make sure that you have included the important directories
within your PATH environment variable, such as C:\Python34, C:\Python34\DLLs, C:
ot

\Python34\Lib\lib-tk, and C:\Python34\Scripts. (These example paths assume Python


version 3.4. If you are using a different version of Python, adjust these paths accordingly.)
N

Alternate Ways to Distribute Packages


o

You may want to distribute your packages through means other than PyPI. You can set up your Alternate Ways to
own repository as an alternative to PyPI, or you can deliver files in a format that is ready to install Distribute Packages
D

directly. The Python distutil utility provides for packaging and installing applications using
several different formats. You can choose to distribute your application as source code for everyone
to see, or you can choose to distribute your application as compiled Python code to hide your code.
You can also choose to distribute your application using a Windows installer format, a Linux
package management format, or even a simple TAR or ZIP file. PyCharm's Tools→Run setup.py
Task menu provides a way to run one of these packaging options without having to enter
command-line commands directly.

Lesson 7: Packaging an Application for Distribution | Topic A


146 | Python® Programming: Advanced

Minimal Structure
Minimal Structure When you are preparing to create a Python distribution package, you must follow a strict structure
format. The package itself is nothing more than a package folder that contains your application files.
The folder will contain your Python code files, any data files required for your application, as well as
any unit test files that you may have built.
The key to the package folder is the __init__.py file. Its presence in a folder indicates that the folder
is a Python library and contains code files that Python should scan when searching for library
modules. The __init__.py file itself doesn't need to contain any data; it just needs to exist.

e
The main configuration file for a Python package is the setup.py file. It tells the Python installation

ut
program important information about the package. This is where you configure your application
package name, any version number information, who wrote the application, how to contact the
author, and what files need to be installed along with the program files.

ib
Dependencies

tr
Dependencies Just about every Python application requires some external libraries and/or data files to operate. For

is
example, the Python Pizza Calculator server application requires the sqlite3, socket, json,
threading, and tkinter libraries to run. These particular libraries are included in the standard
Python distribution, but you need to let the Python installer know if the package includes other

D
libraries required for your application to run properly.
You also need to let the Python installer know about any data files that the application requires. The

or
Python Pizza Calculator uses the pizza.db database file to store the toppings and price
information. Since that file is not a Python program file, it needs to be treated differently in the
package.
e
Guidelines for Packaging a Python Project
at

Note: All Guidelines for this lesson are available as checklists from the Checklist tile on the
lic

CHOICE Course screen.

Planning to Package a Follow these guidelines for packaging a Python project.


Python Project
up

Planning to Package a Python Project


Follow these guidelines when packaging a Python project:
• Consider how you plan to distribute the project, since this will affect how you set up the
D

package.
• If appropriate, include documentation for your users, such as README files, requirements, and
so forth.
ot

• If possible, test the package by installing it on various computers that represent the types of
systems your end users will have and using test utilities to test the packaging.
N

Use Pip Install to Install


a Package from a Local Use Pip Install to Install a Package from a Local Package Archive
Package Archive
To use pip install to install a package from a local package archive:
o

• Open a command prompt.


D

• Make sure the current directory contains the archive file for the package you want to install.
• Type pip install followed by a space and the name of the package you want to install—for
example pip install pyinstaller-3.2.zip.
• Press Enter.

Lesson 7: Packaging an Application for Distribution | Topic A


Python® Programming: Advanced | 147

Use Project Interpreter


Use Project Interpreter to Install a Package to Install a Package
To use Project Interpreter to install a package from within PyCharm:
• In PyCharm, select File→Settings.
• In the left pane, select Project Interpreter.
• In the right pane, select +.
• Type a search term to locate the package you want to install.
• In the left pane, select the package you want to install.

e
• Select Install Package.

ut
Access the Checklist tile on your CHOICE Course screen for reference information and

ib
job aids on How to Create and Install Packages.

tr
is
D
or
e
at
lic
up
D
ot
N
o
D

Lesson 7: Packaging an Application for Distribution | Topic A


148 | Python® Programming: Advanced

ACTIVITY 7-1
Creating a Package Structure

Data Files

e
All project files in Desktop\AdvPython\Packaging an Application for Distribution\PizzaServer.

ut
Activity: Creating a
Package Structure Scenario
You are ready to package the Python Pizza Calculator server so it can be installed on other

ib
computers. Before you can begin, you'll need to use PyCharm to create the basic structure for your
application.

tr
is
1. Launch PyCharm and open the Python Pizza Calculator server project.
a) Launch JetBrains PyCharm Community Edition 3.4.
b) Select Open Directory and navigate to Desktop\AdvPython\Packaging an Application for

D
Distribution.
c) Select PizzaServer and select OK.

or
2. Create a Python package folder in the project.
a) In the left window, right-click on the PizzaServer project name.
b) From the menu, select New→Python Package.
e
c) In the Enter new package name text box, type pizzaserver and select OK.
The new pizzaserver package folder is created in the project folder. It contains an empty initialization
at

file, __init.py__.
d) Observe the package folder.
lic

It has a special folder icon that shows that it is a packaging folder.

3. Move essential files into the package folder.


up

a) In the Project window, select create-database.py.


b) Press and hold Shift, then select update-database.py to include all files between the two you
selected as shown.
D
ot
N
o
D

Lesson 7: Packaging an Application for Distribution | Topic A


Python® Programming: Advanced | 149

c) Drag the selected files into the pizzaserver package folder.

e
ut
ib
d) Select OK.

tr
The files are now indented beneath the pizzaserver package folder, so they will all be included in the
package.

is
4. Create a setup.py file for your project.

D
a) In the left window, select the PizzaServer project.

Note: Be careful to select the PizzaServer project folder, not the pizzaserver
package folder.
b) From the PyCharm menu bar, select Tools→Create setup.py.
c) Fill in the New Setup Script form with the package information.
or
e
at
lic
up
D
ot
N
o
D

d) Select OK to build the setup.py file.


Setup.py is created and shown in the editor.

5. Make note of the various package dependencies.


a) From the pizzaserver package folder, open each of the .py files (except for __init__.py), and note the
various packages that are imported.

Lesson 7: Packaging an Application for Distribution | Topic A


150 | Python® Programming: Advanced

• create-database.py imports __________________________.


• getPPCData.py imports __________________________.
• ppc-threaded-server.py imports __________________________.
• update-database.py imports __________________________.
The following packages are imported: sqlite3, socket, json, threading, tkinter. These
packages are all included in the standard library.
b) Right-click the update-database.py tab and select Close All.

6. Examine the list of package dependencies in setup.py.

e
a) Open setup.py for editing.

ut
b) Examine setup.py.

ib
tr
is
D
or
The setup is initialized using the values you provided. If you needed to add package dependencies,
e
you could modify the packages value to include more package names after 'pizzaserver'.
at
lic
up
D
ot
N
o
D

Lesson 7: Packaging an Application for Distribution | Topic A


Python® Programming: Advanced | 151

TOPIC B
Generate the Package Distribution Files
Once you've completed configuring the setup.py file, you're ready to bundle your application for
distribution. There are several different ways you can bundle your package.

e
Packaging Options

ut
When you create a package using either the Run setup.py Task menu from PyCharm or Packaging Options
setuptools from the command line, you'll need to specify the type of packaging operation you

ib
want to perform. Typical options include the following.

tr
Item Description

bdist Create a built (binary) distribution.

is
bdist_dumb Create a "dumb" built distribution.
Create an executable installer for Microsoft® Windows®.

D
bdist_msi
bdist_rpm Create an RPM distribution.
bdist_wininst
build
build_py
Build everything needed to install. or
Create an executable installer for Microsoft Windows.

Build pure Python modules (copy to build directory).


e
build_ext Build C/C++ extensions (compile/link to build directory).
at

build_clib Build C/C++ libraries used by Python extensions.


build_scripts "Build" scripts (copy and fixup #! line).
lic

clean Clean up temporary files from the build command.


install Install everything from build directory.
up

install_lib Install all Python modules (extensions and pure Python).


install_headers Install C/C++ header files.
install_scripts Install scripts (Python or otherwise).
D

install_data Install data files.


register Register the distribution with the Python package index.
ot

sdist Create a source distribution (tarball, zip file, etc.).


N

upload Upload binary package to PyPI.

When you using PyCharm's Run setup.py Task menu to generate a package, you are prompted to
o

select an option. Each option may include its own assortment of settings, which are presented in
PyCharm through a dialog box.
D

Access the Checklist tile on your CHOICE Course screen for reference information and
job aids on How to Generate Package Distribution Files.

Lesson 7: Packaging an Application for Distribution | Topic B


152 | Python® Programming: Advanced

ACTIVITY 7-2
Packaging the Python Pizza Application

Scenario

e
You have prepared the Python Pizza Calculator server application for the packaging process. All

ut
that is left now is to generate and release the distribution files.
Activity: Packaging the
Python Pizza Application

ib
1. Run the packaging task.
a) In the PyCharm window, select the PizzaServer project.

tr
b) Select Tools→Run setup.py Task.
c) Scroll to view the various types of packages you can build.

is
D
or
e
at
lic
up

d) Type sdist to select the sdist distribution method, and press Enter.
D

e) If the only option shown in the Run Setup Task sdist dialog box is Command Line, then select
Expand Options.
ot
N
o
D

Lesson 7: Packaging an Application for Distribution | Topic B


Python® Programming: Advanced | 153

f) Examine the options for this distribution type.


You can change any setting from the default value by providing your own value in the form.

e
ut
ib
tr
is
D
or
e
at

In this case, you'll use all of the default options.


g) Select OK.
The distribution is created, as you can see by the dist folder that has been added to the Project
lic

window.

2. View the distributable package.


up

a) In the Project window, expand the dist folder.


D
ot
N
o

The folder contains a ZIP file that in turn contains the application package.
D

Lesson 7: Packaging an Application for Distribution | Topic B


154 | Python® Programming: Advanced

b) In the Project window, right-click PizzaClient-1.0.zip, and select Show in Explorer.

e
ut
ib
3. Examine the ZIP file.
a) In the File Explorer window, double-click PizzaClient-1.0.zip to open it as a compressed folder.
The ZIP file contains one folder, PizzaServer-1.0.

tr
b) Open PizzaServer-1.0.
The package includes a setup.py script, PKG-INFO file, and pizzaserver folder.

is
c) Open pizzaserver.
The folder includes all of the Python files you included in the package folder, but not the pizza.db

D
database file.
d) Close the File Explorer window.

4. Add package data to the setup script.


or
a) In PyCharm, add a new line to setup.py as shown.
e
at
lic
up
D
ot

5. Rebuild the package.


N

a) In the PyCharm window, select the PizzaServer project.


b) Select Tools→Run setup.py Task.
c) Type sdist to select the sdist distribution method, and press Enter.
o

d) Select OK.
The distribution is created, replacing the old ZIP file with a new one.
D

6. Examine the ZIP file.


a) In the Project window, right-click PizzaClient-1.0.zip, and select Show in Explorer.
b) In the File Explorer window, double-click PizzaClient-1.0.zip to open it as a compressed folder.
c) Open PizzaServer-1.0.
d) Open pizzaserver.

Lesson 7: Packaging an Application for Distribution | Topic B


Python® Programming: Advanced | 155

The folder includes all of the Python files you included in the package folder, as well as the pizza.db
database file.

7. Close your work.


a) Close the File Explorer window.
b) Close the project.
c) Exit PyCharm.

e
ut
ib
tr
is
D
or
e
at
lic
up
D
ot
N
o
D

Lesson 7: Packaging an Application for Distribution | Topic B


156 | Python® Programming: Advanced

TOPIC C
Generate a Windows Executable
You've created an application that you want to distribute to users who do not have Python installed
on their computer. Fortunately, you can provide the application along with its own instance of
Python, essentially delivering a complete Windows executable version of the application.

e
ut
PyInstaller
PyInstaller PyInstaller is a Python package that bundles a Python application and all of its dependencies

ib
(including Python itself) into a complete deliverable. A user can run the packaged application
without having to install a separate Python interpreter and related support modules. PyInstaller

tr
works with Python applications created in Python 2.7 and Python 3.3 and later. It supports both
windowed (for example, those that use wxPython) and console apps.

is
PyInstaller works with Windows, Mac OS X®, and Linux. But it does not generate packages across
platforms. For example, to create a Windows executable package, you must run PyInstaller on a
Windows computer. PyInstaller is available through PyPI, and other sources such as GitHub® and

D
the PyInstaller website (www.pyinstaller.org).

or
Access the Checklist tile on your CHOICE Course screen for reference information and
job aids on How to Generate a Windows Executable.
e
at
lic
up
D
ot
N
o
D

Lesson 7: Packaging an Application for Distribution | Topic C


Python® Programming: Advanced | 157

ACTIVITY 7-3
Generating a Windows Executable

Data Files

e
Desktop\AdvPython\Packaging an Application for Distribution\Install\PyInstaller-3.2.zip

ut
All project files in Desktop\AdvPython\Packaging an Application for Distribution\PizzaClient
Generating a Windows
Scenario Executable

ib
Computers that will run the Python Pizza Calculator client will not necessarily already have
Python installed, so you will generate a version of the application that will include its own Python

tr
runtime environment.

is
1. Locate a local copy of the PyInstaller package.

D
a) In File Explorer, open the AdvPython folder.
b) Open the Packaging an Application for Distribution folder.
c) Open the Install folder.

or
e
at
lic

This folder contains the PyInstaller package in the PyInstaller-3.2.zip file. You will use Pip to install
up

the package.

2. Install PyInstaller from a command console.


D

a) In the File Explorer window, click a blank area to make sure no file is selected.
b) In the File Explorer window, press and hold Shift and then right-click a blank area. Select Open
command window here.
ot

A command console opens, and the current directory is Desktop\AdvPython\Packaging an


Application for Distribution\Install.
c) Type pip install pyinstaller-3.2.zip and press Enter.
N

The PyInstaller package is installed.


d) After PyInstaller has installed, close the command console window.
o

3. Launch PyCharm and open the Python Pizza Calculator client project.
a) Launch JetBrains PyCharm Community Edition 3.4.
D

b) Select Open Directory and navigate to Desktop\AdvPython\Packaging an Application for


Distribution.
c) Select PizzaClient and select OK.

4. Use PyInstaller to create a Windows executable.


a) Select Tools→Open terminal.
b) Type pyinstaller ppc-client.py and press Enter.

Lesson 7: Packaging an Application for Distribution | Topic C


158 | Python® Programming: Advanced

c) PyInstaller runs in the project directory and creates a build and dist folder.

5. Launch the Python Pizza Calculator server.


a) Select File→Close Project.
To test the PPC client, you don't need to keep its project open, since you can run it directly from its
EXE file. But you will need to launch the server.
b) Select Open Directory and navigate to Desktop\AdvPython\Packaging an Application for
Distribution.
c) Select PizzaServer and select OK.

e
d) In the Project window, right-click ppc-threaded-server.py, and select Run 'ppc-threaded-server'.

ut
ib
tr
is
D
e) Minimize the PyCharm window.
or
e
The server will continue running with the window minimized.
at

6. Run the Python Pizza Calculator client executable.


a) In File Explorer, navigate to Desktop\AdvPython\Packaging an Application for Distribution
lic

\PizzaClient.
The build and dist folders created by PyInstaller are visible here.
up
D
ot
N
o
D

Lesson 7: Packaging an Application for Distribution | Topic C


Python® Programming: Advanced | 159

b) Open the dist folder, and open the ppc-client folder.

e
ut
ib
tr
is
D
This directory contains the files you would distribute to users. These include the ppc-client.exe
executable file, along with runtime files needed to provide the Python environment.
c) Open ppc-client.exe.

or
A console window runs, from which the Python Pizza Calculator is launched. The console output
from your application would appear in the console window, although PyInstaller includes an option to
create an executable that does not display the console window.
e
d) Select Large, Pepperoni, and Calculate Price and verify the application returns a Total of 14.49.
e) Close the Python Pizza Calculator window to exit the application.
at

7. Generate a new executable with no console window.


lic

a) In File Explorer, navigate to Desktop\AdvPython\Packaging an Application for Distribution


\PizzaClient.
b) In the File Explorer window, click a blank area to make sure no file is selected.
c) In the File Explorer window, press and hold Shift and right-click a blank area. Select Open command
up

window here.
You can run PyInstaller directly from a command console (outside of PyCharm).
d) Type pyinstaller ppc-client.py -w and press Enter.
D

You are prompted to replace the previous build that you created.
e) Type y and press Enter.
ot

8. Run the new Python Pizza Calculator client executable.


a) In File Explorer, navigate to Desktop\AdvPython\Packaging an Application for Distribution
\PizzaClient\dist\ppc-client.
N

b) Open ppc-client.exe.
The Python Pizza Calculator is launched without a console window.
o

c) Close the Python Pizza Calculator window to exit the application.


D

9. Examine other PyInstaller options.


a) In the command console window, type cls and press Enter.
Previous information is cleared from the console.
b) In the command console window, type pyinstaller -h and press Enter.
A list of options available for the pyinstaller command are shown.
c) Scroll the console window to view the various options provided by the pyinstaller command.

Lesson 7: Packaging an Application for Distribution | Topic C


160 | Python® Programming: Advanced

10. Clean up the desktop.


a) Close the command console window.
b) Close the File Explorer window.
c) Select File→Close project in PyCharm.
d) Disconnect from the ppc-threaded-server.
e) Close PyCharm.

e
ut
ib
tr
is
D
or
e
at
lic
up
D
ot
N
o
D

Lesson 7: Packaging an Application for Distribution | Topic C


Python® Programming: Advanced | 161

Summary
In this lesson, you created a package structure for a Python application project, and you generated
distribution files.
Encourage students to
Will you distribute your Python applications to other users? use the social
A: Answers may vary. Some Python programmers only develop applications for their own use, so networking tools

e
distribution may not be a matter of concern for them. However, if you intend to distribute your provided on the CHOICE
applications to other users, you should spend some time getting familiar with the packaging options Course screen to follow

ut
up with their peers after
provided for Python.
the course is completed
What sorts of distribution options will you use to distribute your packages? for further discussion

ib
and resources to support
A: Answers will vary, depending on your users, the computer operating systems they use, and whether continued learning.
they already have Python installed.

tr
Note: Check your CHOICE Course screen for opportunities to interact with your classmates,
peers, and the larger CHOICE online community about the topics covered in this course or

is
other topics you are interested in. From the Course screen you can also access available
resources for a more continuous learning experience.

D
or
e
at
lic
up
D
ot
N
o
D

Lesson 7: Packaging an Application for Distribution |


D
o
N
ot
D
up
lic
at
e
or
D
is
tr
ib
ut
e
Python® Programming: Advanced | 163

Course Follow-Up
Congratulations! You have completed the Python® Programming: Advanced course. You have
successfully created, tested, packaged, and delivered Python applications that include graphical user
interfaces, networking, database, and threading features.

What's Next?
Programming Google App Engine™ Applications in Python® will show you how to use your Python skills

e
to develop web applications that take advantage of Google cloud services. In this course, you will
learn how to create web applications powered by Google's App Engine, a cloud computing

ut
platform. You'll learn how to program these apps in Python and supplement them with languages
like HTML and CSS.

ib
You are encouraged to explore Python further by actively participating in any of the social media
forums set up by your instructor or training administrator through the Social Media tile on the
CHOICE Course screen. You may also wish to explore the official Python documentation website

tr
at https://docs.python.org/3/ for more information about the language.

is
D
or
e
at
lic
up
D
ot
N
o
D

Course Follow up
D
o
N
ot
D
up
lic
at
e
or
D
is
tr
ib
ut
e
Solutions

e
ut
ib
ACTIVITY 2-1: Designing a GUI

tr
is
2. How many windows will the application use?
A: While applications may have multiple windows, this application is simple enough that it can
be implemented in one window.

D
3. What type of widget(s) might you provide to enable the user to select a pizza size?

or
A: Since only one size should be selected from the three options, a group of radio buttons is
probably the most appropriate choice for this. Another option would be a list box configured to
allow only one item to be selected.

4. What type of widget(s) might you provide to enable the user to select toppings?
e
A: Since no selection, one selection, or multiple selections should be allowed, a group of check
at

boxes would be an appropriate choice for this. Another option would be a list box configured to
allow multiple items to be selected.
lic

5. What type of widget(s) might you provide to enable the user to clear (reset) the selections?
A: A button would be appropriate for this. When selected, a Reset button could trigger an
action that resets the application widgets back to their original selection states.
up

6. What type of widget(s) might you provide to enable the user to calculate the total?
A: A label or text box could be used to display the resulting price. There are different ways to
trigger the calculation. For example, you might calculate a new result automatically each time
D

the user changes the size or toppings. Or you might provide a separate Calculate price button
that displays the updated total when the user selects the button.
ot

ACTIVITY 3-1: Designing a Database for Python Pizza


N

1. What data elements will be needed in the database?


o

A: For the Python Pizza Calculator, three data elements will be needed: the list of toppings, the
pizza price for each size, and the price for toppings for each pizza size.
D

2. What groups of common data will be needed to contain the data elements?
A: The data normalization process can be somewhat subjective and tricky. First, determine the
common groups for the data. While there may be various ways of doing this, for the Python
Pizza Calculator, you'll provide two general categories of data elements: toppings and prices.
166 | Python® Programming: Advanced

3. Which data elements belong to which group?


A: For the toppings group, you'll just have the topping data element. For the prices group,
you'll need to specify the price, and what the price is for (the product). That makes for two
data elements—the product and the price.

4. What data type will be required for each element?


A: Again, there is some flexibility here, but in the next activity, you'll store the topping
name as a text value using the varchar data type. Since the topping names aren't too
long, you'll use a 15-character data constraint. For the product data field, you'll store the

e
pizza size and topping size as a text value, again using the varchar data type. You'll
also use the 15-character data constraint for this data field. For the price data field, you'll

ut
need to store the product price as a dollar amount, including two decimal places for the
cents. You'll use the decimal data type to do that.

ib
ACTIVITY 4-1: Defining an Application Protocol for

tr
the Python Pizza Calculator

is
1. What connection protocol and port will you use for the application?

D
A: Since the Python Pizza Calculator needs to accurately send topping and price data
across the network, TCP is an appropriate choice. Regarding the port, many numbers are
available and appropriate. (In the activity, you'll use port 8000.)

server application. Which one should it be?


or
2. You will modify the Python Pizza Calculator to be either the client application or the

A: Since customers will run the Python Pizza Calculator window, you'll use that as the
e
client device. You'll create a separate server program to serve the toppings list and prices
dictionary values. The server will listen on TCP port 8000 and the client (the Python Pizza
at

Calculator window) will request a connection to the server program.


lic

3. Which application should initiate the connection?


A: The server will remain running, listening for connections. Clients will come and go.
After a client initiates a connection, the server will send a welcome message to the client
to identify itself. The client must be able to read that message.
up

4. What requests must the server be able respond to?


A: In addition to opening to a new connection, the server must be able to provide
D

toppings, prices, or terminate the connection (exit). The client will send these as text
commands to the server. The server will return data in response to received client
commands. If the server receives a topping command, it will send the toppings list. If
the server receives a prices command, it will send the prices dictionary object. Finally, if
ot

the server receives an exit command, it will terminate the connection with the client.
N

ACTIVITY 6-1: Planning for TDD


o
D

1. In a sentence or two, define what a factorial is.


A: The mathematical definition for the factorial of a positive integer value is the
multiplication of all the previous integer values up to that value. Thus, the factorial of 5 is
1 * 2 * 3 * 4 * 5 = 120.

Solutions
Python® Programming: Advanced | 167

2. What results should be produced for special numbers and extremes. For example, what is the factorial
of 0? What is the factorial of a negative number?
A: The mathematical definition of the factorial of 0 is 1. There is no mathematical definition for the
factorial of a negative number. Our function will return a failure condition if the calling program supplies
a negative value.

3. What test cases might you use to test for various normal numbers and special numbers?
A: You might test that various positive numbers return the correct factorial value—perhaps a small,
medium, and large value. For example, if our test submits the value of 5 (a small number), the

e
factorial() function must return a value of 120. It should also ensure that submitting a value of 0
returns a value of 1. It should also ensure that submitting a negative value returns a False value. While

ut
not a requirement, the factorial() function must also be able to detect if a non-numeric value is
submitted. If it detects a non-numeric value, it should also return a False value. These can serve as
the basis for your tests.

ib
tr
is
D
or
e
at
lic
up
D
ot
N
o
D

Solutions
D
o
N
ot
D
up
lic
at
e
or
D
is
tr
ib
ut
e
Glossary

e
ut
ib
assertion constructor
A statement in a unit test function that A special method, defined within a class

tr
determines if a particular rule passes or using the __init__ keyword, that runs
fails. when an object of that class is instantiated.

is
attribute cursor

D
Features of an object (such as the weight, A pointer to a particular storage location
engine, and number of doors of a car). A within a database, which you can use to
class can contain many attributes, each navigate through a database and

class
or
describing a different feature of the object. manipulate individual objects in the
database.

daemon
e
Data and functions, grouped together into
a single entity, that can be instantiated to Processes that run in the background and
at

create an object. can continue to run after the main thread


completes.
class factory
lic

A class that is capable of creating objects destructor


of one or more other class types. A special method, defined within a class
using the __del__ keyword, that runs when
up

client/server paradigm an object of that class is destroyed.


A model for delegating processing
capabilities between multiple systems, event
D

including a server, which provides access A condition or combination of conditions


to shared resources (such as stored files or that trigger a method to run.
data in a database), and one or more
ot

clients, which communicate with the server event handler


to gain access to those resources. A method that runs in response to a
N

particular user action, such as selecting a


comparison method button or pressing a key on the keyboard.
A function of a class, which can be used to
o

determine if two objects of that class are file pointer


the same (equal) or different (greater than, An object that tracks the location of data
D

less than, etc.). Python provides a variety being accessed within a file.
of standard comparison methods that you
can customize in your own classes to frame
enable objects of that class to be easily An object that serves as the main content
compared. area for a window, which contains other
170 | Python® Programming: Advanced

user interface objects that appear within packing method


the window. A scheme for laying out user interface
components within a window, which
getter attempts to pack widgets into a window as
A special method used to provide efficiently as possible in the available space.
protected read access to data values within
a class. positional method
A scheme for laying out user interface
grid method

e
components within a window, which
A scheme for laying out user interface requires you to provide a specific X,Y

ut
components within a window, which uses location for each widget.
a system of columns and rows to position
components. property

ib
A protected attribute of a class that can be
inheritance set only by using special instance methods

tr
An aspect of object-oriented programming called setters, and whose values can be
that enables developers to define a subclass read only by using special class methods

is
that inherits attributes and methods of a called getters.
superclass.

D
PyInstaller
locking A Python package that bundles a Python
A Python feature that enables one thread application and all of its dependencies,
of execution to place a hold on processing
while it performs a crucial code segment.
While the lock is in place, the operating
system blocks any other threads from
or including Python, into a complete
deliverable.

PyPI
e
running. (Python Package Index) A central
at

clearinghouse for shared Python


magic method applications and code.
Built-in methods that you can use when
lic

defining a class to add certain types of serialization


functionality commonly required by A means of encoding complex data types
classes, including constructors, destructors, (objects) for transmission or storage as a
up

comparison methods, and so forth. simple text value.

method setter
D

Essentially, a custom function that the A special method used to provide


developer adds to a particular class, to protected write access to data values within
enable objects of that class to be a class.
ot

manipulated or perform certain tasks


specific to the class. subclass
A class based on another class, which
N

network byte order inherits attributes and methods of the


A data format optimized for sending data superclass, and can add its attributes and
o

across a network connection. methods specific to the subclass.


D

package folder superclass


A special container within an application The base class from which a subclass is
project that contains only the files that you derived.
intend to be delivered to the user's
computer when the package is installed. synchronization
A means through which different threads
can be prevented from simultaneously

Glossary
Python® Programming: Advanced | 171

attempting to access each other's data


resources (causing a collision) by locking access
to those resources so only one thread can
access them at a time.

TDD
(test-driven development) A software
development methodology that involves

e
designing and implementing tests before
writing the code that will be tested. Because

ut
tests are created first, they can be used to drive
development. Once a unit of code is thought

ib
to be complete, it can be tested and modified
repeatedly until it passes testing. Once a unit
has passed, its unit tests can remain in place to

tr
ensure that if changes are made to code later
on, they do not cause the code fail.

is
threading

D
A means of coordinating the execution of
multiple blocks of code that can share the
same data.

transaction
A means of grouping a series of database
or
e
manipulation tasks such that all of the tasks
must complete successfully. If any task is
at

unsuccessful, the entire group of tasks will be


rolled back, as though none of them had been
lic

completed.

widget
A user interface component.
up

wireframe
A type of drawing or diagram that illustrates
D

the logical design of a user interface, without


necessarily focusing on the visual style of the
user interface.
ot
N
o
D

Glossary
D
o
N
ot
D
up
lic
at
e
or
D
is
tr
ib
ut
e
Index

e
ut
ib
tr
A E

is
assertions 127 event handlers 47
attributes events 47
defined 2

D
F
C factory method 25
classes
defined 2
class factories
or
G
e
abstract 26 getters 5
polymorphic 25 graphical user interface, See GUI
at

simple 25 grid method 40


class methods 3 GUI
lic

comparison methods 16 frame 34


constructor methods 15 libraries 34, 38
cursor 64 widgets 34
up

window positioning methods 40

D
I
daemons 104
D

database queries 75 inheritance 7


databases instance methods 3
ot

data types 61
supported by Python 61 J
data corruption json library 91
N

thread local storage 112


data management
file pointer 60
L
o

files 60 libraries
D

data transmission json 91


network byte order 90 queue 113
serialization 91 socket 89
destructor methods 15 threading 104
tkinter 38, 40
unittest 127
174 | Python® Programming: Advanced

M setters 5
socket library
magic methods 15
client 90
menu bars 49
common methods 89
methods
server 89
class 3
SQLite3
comparison 16
database construction 65
constructor 15
database methods 64
defined 2

e
database queries 75
destructor 15
overview 64

ut
factory 25
subclass 7
instance 3
superclass 7
magic 15

ib
synchronization
numeric 18
locking feature 112
overview 3

tr
property 6
multiprocessing T

is
vs. threading 113 TCP 86
TDD

D
N benefits 126
overview 126
network programming
three groups of testing 127
client/server paradigm 86
TCP 86
UDP 86
numeric methods 18
or
test-driven development, See TDD
threading
overview 104
e
vs. multiprocessing 113
threading library 104
at

P thread local storage 112


packaging applications thread-safe data structures 113
lic

alternate methods 145 tkinter library 38, 40


dependencies 146 transactions 64
options 151 Transmission Control Protocol, See TCP
up

package folder 146


package name 144 U
pip install command 145
UDP 86
D

PyInstaller 156
unit testing
PyPI 144
assertions 127
packing method 40
framework 127
ot

positional method 40
TestCase class 130
properties 5
unittest library 127
property method 6
N

unit test suite feature 136


PyInstaller 156
User Datagram Protocol, See UDP
PyPI 144
user interface objects 34
o

Python Package Index, See PyPI

W
D

Q
window positioning methods 40
queue library 113
wireframe 35

S
serialization 91

Index
e
ut
ib
tr
is
D
or
e
at
lic
up
D
ot
N
o
D

094012I rev 1.0


ISBN-13 978-1-4246-2699-1
ISBN-10 1-4246-2699-4

You might also like

pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy