0% found this document useful (0 votes)
3 views

Python Debugging Handbook.marking

This document is a comprehensive guide on Python debugging, detailing methods, tools, and best practices for identifying and resolving issues in code. It covers foundational concepts, debugging steps, and provides examples of common errors and their resolutions. The book aims to equip readers with a solid understanding of debugging in Python, particularly using the Anaconda and Spyder environments.

Uploaded by

聂乐春
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
3 views

Python Debugging Handbook.marking

This document is a comprehensive guide on Python debugging, detailing methods, tools, and best practices for identifying and resolving issues in code. It covers foundational concepts, debugging steps, and provides examples of common errors and their resolutions. The book aims to equip readers with a solid understanding of debugging in Python, particularly using the Anaconda and Spyder environments.

Uploaded by

聂乐春
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 220

2

Python Debugging
RL Zimmerman

3
Table of Contents

1. Introduction
1.1 Overview
1.2 What This Book is About
1.3 What’s Next?
2. Debugging Overview
2.1 Plan for Debugging
Start Small
Keep Multiple Versions of Your Code
Intended Outcome
Test Data Files
Plan for Tomorrow
2.2 Debugging Steps
Logbook
Divide and Conquer
Backup Files Before Debugging
Problem Statement

4
Doubt Everything
Look Around Your Environment
Create a List of Suspects
What Do You Think is the Cause?
Refine Your Experiment
Experiment
Success at Last
2.3 The Debugging Environment
Python
Anaconda
Spyder
Run a Script or Program
2.4 Help
2.5 What’s Next?

3. Python Basics
3.1 Statements
3.2 Python Syntax
3.3 Objects
3.4 Immutable Objects
3.5 Variables
3.6 Types of Data

5
What is the Data Type?
Converting Data Types
The ‘None’ Value
3.7 Numbers
3.8 Strings
3.9 Introduction to Data
Structures
3.10 List
Iterate Through Items in a List
3.11 Tuple
Iterate Through Items in a Tuple
3.12 Dictionary
Create a Dictionary
Assign a Dictionary Value Using the Key
Name
Add a New Key to an Existing Dictionary
Iterate Through Key-Pairs in a Dictionary
Iterate Through Keys in a Dictionary
Access the Value of a Dictionary Item
3.13 Set
3.14 Comparison Operators
3.15 Control Statements
6
3.16 Indented Code (a Suite)
3.17 Functions and Methods
Defining a Function
Parameters
Arguments
KEYWORD ARGUMENTS
POSITIONAL ARGUMENTS
OPTIONAL ARGUMENTS
AN ARBITRARY NUMBER OF ARGUMENTS
HOW TO VIEW THE FUNCTION ARGUMENT DEFINITION
Calling a Function or Method
Function Return Value
All Paths Do Not Have a Return Value
More than One Return Value
The Type of Return Value
3.18 Classes
Create a Class
The DocString
Variables - Attributes
Instance Variables and Class Variables
Create an Instance of the Class
Methods
Dotted Notation for Attributes
Calling a Method
3.19 Attributes

7
4. Debugging Tools
4.1 Debugging Overview
4.2 Add Print Statements to Your
Script
Indenting Loop Print Statements
4.3 Debug Mode
End Debug Mode
4.4 Variable Explorer
4.5 Example: My Program Loops
and Never Ends
4.6 Debug Commands
4.7 Interactive Mode
Increment Counters in the Console
Watch Out for Changing Values
iPython Session
4.8 Introspection
Variables and Objects in Memory
Using ? in the Console
dir()
help()
The Inspect Library

8
The type() Function
The id() Function
The repr() Function
The len() Function
4.9 Logging
4.10 The timeit() Function
4.11 Focused Testing
Actual Result
Incorrect Code
4.12 Create Test Data

5. Exceptions
5.1 Kinds of Errors
Syntax
Logic or Semantic
Runtime
5.2 The Stack Trace or Traceback
Don’t Be Fooled
5.3 Try and Except
5.4 Raise
5.5 Assert
5.6 Built-in Error Types
9
ArithmeticError
AssertionError
AttributeError
EOFError
FloatingPointError
ImportError
Indentation Error
IndexError
IOError
KeyError
KeyboardInterrupt
LookupError
MemoryError
ModuleNotFoundError
NameError
OSError
OverflowError
RecursionError
RuntimeError
StopIteration
SyntaxError
TabError
SystemError
SystemExit
TypeError
ValueError
ZeroDivisionError

10
6. Try This
6.1 What is the Object Value?
6.2 String and Number Variable
Values
Print the Value of a String Variable
Inspect a Number Variable in Debug Mode
Inspect a String Value with Interactive Mode
6.3 Tuple Objects and Values
Print All Tuple Item Values
Print a Tuple Item Value
Inspect All Tuple Items in Interactive Mode
Inspect A Tuple Item in Interactive Mode
6.4 List Objects and Values
Print All List Item Values
Print the Value of a List Item
Inspect a List Item in Debug Mode
Inspect All Items of a List in the Console
Inspect a List Item in the Console
6.5 Dictionary Objects and
Values
Print the Value of a Dictionary Key-Pair
Inspect All Dictionary Items in the Console
Inspect a Dictionary Item Value in the
Console

11
Inspect a Dictionary Item in Variable Explorer
6.6 Does the Object have a Value
of None or Whitespace?
Whitepsace
6.7 What is the Object Type?
6.8 What is the Length of the
Object?
6.9 What are the Function
Arguments?
The Function Call Signature
6.10 What is the Return Object of
the Function?

7. Examples
Ex 7.1 List Index Out of Range
Intended Outcome
Actual Result
Incorrect Code
Debugging Experiment
How to Resolve the Issue
Good Code
Reference
Ex 7.2 Index Error
12
Intended Outcome
Actual Result
Incorrect Code
Debugging Steps
How to Resolve the Issue
Good Code
Reference
Ex 7.3 Wrong Variable
Intended Outcome
Actual Result
Incorrect Code
Debugging Steps
How to Resolve the Issue
Good Code
Reference
Ex 7.4 Invalid Assignment
Intended Outcome
Actual Result
Incorrect Code
Debugging Steps
How to Resolve the Issue
Good Code
Reference
Ex 7.5 While Indentation Error
Intended Outcome
Actual Result

13
Incorrect Code
Debugging Steps
How to Resolve the Issue
Good Code
Reference
Ex 7.6 Incorrect Method
Arguments
Intended Outcome
Actual Result
Incorrect Code
Debugging Experiment
How to Resolve the Issue
Good Code
Reference
Ex 7.7 Empty Block of Code
Intended Outcome
Actual Result
Incorrect Code
Debugging Steps
How to Resolve the Issue
Good Code
Reference
Ex 7.8 Parentheses Not Matched
Intended Outcome
Actual Result
Incorrect Code
14
Debugging Steps
How to Resolve the Issue
Good Code
Reference
Ex 7.9 Missing Colon
Intended Outcome
Actual Result
Incorrect Code
Debugging Steps
How to Resolve the Issue
Good Code
Reference
Ex 7.10 Case Sensitive
Intended Outcome
Actual Result
Incorrect Code
Debugging Steps
How to Resolve the Issue
Good Code
Reference
Ex 7.11 Missing Keyword
Intended Outcome
Actual Result
Incorrect Code
Debugging Steps
How to Resolve the Issue

15
Good Code
Reference
Ex 7.12 Illegal Character
Intended Outcome
Actual Result
Incorrect Code
Debugging Steps
How to Resolve the Issue
Good Code
Reference
Ex 7.13 Undefined Name
Intended Outcome
Actual Result
Incorrect Code
Debugging Steps
How to Resolve the Issue
Good Code
Reference
Ex 7.14 FileNotFound
Intended Outcome
Actual Result
Incorrect Code
Debugging Steps
How to Resolve the Issue
Good Code
Reference

16
Ex 7.15 Error Adding Numbers
Intended Outcome
Actual Result
Incorrect Code
Debugging Steps
How to Resolve the Issue
Good Code
Reference
Ex 7.16 Misspelled Keyword
Intended Outcome
Actual Result
Incorrect Code
Debugging Steps
How to Resolve the Issue
Good Code
Reference
Ex 7.17 Value is None
Intended Outcome
Actual Result
Incorrect Code
Debugging Steps
How to Resolve the Issue
Good Code
Reference
Ex 7.18 Method Not Found
Intended Outcome
17
Actual Result
Incorrect Code
Debugging Steps
How to Resolve the Issue
Good Code
Reference
Ex 7.19 Module Not Found
Intended Outcome
Actual Result
Incorrect Code
Debugging Steps
How to Resolve the Issue
Good Code
Reference
Ex 7.20 Key Not in Dictionary
Intended Outcome
Actual Result
Incorrect Code
Debugging Experiment
How to Resolve the Issue
Good Code
Additional Troubleshooting
Reference
Ex 7.21 Incorrect Argument Type
Intended Outcome
Actual Result

18
Incorrect Code
Debugging Steps
How to Resolve the Issue
Good Code
Reference
Ex 7.22 Name Error
Intended Outcome
Actual Result
Incorrect Code
Debugging Steps
How to Resolve the Issue
Good Code
Reference
Ex 7.23 Value Error
Intended Outcome
Actual Result
Incorrect Code
Debugging Steps
How to Resolve the Issue
Good Code
Reference
Ex 7.24 Divide by Zero Error
Intended Outcome
Actual Result
Incorrect Code
Debugging Steps

19
How to Resolve the Issue
Good Code
Reference
Ex 7.25 Math Logic Error
Intended Outcome
Actual Result
Incorrect Code
Debugging Steps
How to Resolve the Issue
Good Code
Ex 7.26 ValueError Assigning
Date
Intended Outcome
Actual Result
Incorrect Code
Debugging Steps
How to Resolve the Issue
Good Code
Reference

Appendix - URLs
Arguments
Assert
Attributes

20
Built-in Functions
Calls
Classes
Comparisons
Containers
doctest
Functions
Glossary
The if Statement
Immutable
Inspect
Interactive Mode
Iterable and Iterations
Logging
Magic Functions
Methods
Objects
Parameters

21
The pass Statement
The return Statement
State
Statements
timeit
The try Statement
Types
Values

Conclusion

22
1. Introduction

Debugging is the process of finding and removing “bugs”


or defects(缺陷) in a program. To help my daughter with
her first Python class, I looked around for information on
debugging that I could share with her. I wanted a simple
guide with everything in one place and suggestions for how
to go about the process of debugging. Initially, my research
focused on gathering examples of common issues, but I knew
something more was needed. After all, what happens if
there is no example of the “bug” that you’re experiencing?
I knew I needed to provide a debugging “foundation.” Not
just how to use debugging tools, but when to take action and
why. With that goal in mind, Chapters 1 through 6 build a
调试库 debugging arsenal, so you’re ready to tackle the examples in
Chapter 7. Each example begins with “References” to the
related topics covered in earlier chapters. So theoretically,
you could jump right into the examples in Chapter 7.
This book includes an extensive and detailed Table of
Contents. I also made a point to cross-reference topics so
you can easily locate whatever you’re interested in from any
point in the material. This approach means you can pick up
the book at any time and quickly jump back in where you left
off. Or if you prefer, you can hop around from topic to topic
with as much detail as you want.
Hopefully, after reading this book, you won’t feel like this
man who posted a plea for help on a chat board. His
frustration show’s through in his comment, “For the love of

23
God, how is this done?” Instead, you’ll know exactly how it’s
done and have fun doing it!

1.1 Overview
How you may ask, are we going to build your debugging
arsenal? Let’s begin with these topics.

• How to use the debug environment.


• The Python Error Codes and specific examples of how they
happen.
• Step-by-step instructions on the process of debugging
code.
• Finding the information you need to modify your
program : help on Syntax, Functions, Classes, and more.
The goal of debugging is a working program, and
debugging is just part of the process of writing code. When I
realize I have a “bug,” I’ll experiment and try a few things to
find a clue where the issue is. You’ll see this process in the
examples in Chapter 7, where I use different approaches
from my “debugging toolbox” to isolate an issue. You might
take a different approach to the sample problem, and there is
no wrong approach. The idea is to try a few things and see
what works.
In this book, I demonstrate Python using the open-source
Anaconda Data Science Distribution that includes Python
version 3.7. Spyder, the Scientific Python Development
Environment, comes with Anaconda. You may notice slight
differences in screenshots, depending on whether I am using
Spyder on my Windows or Mac computer.

1.2 What This Book is


24
About
My intent in writing this book was not to provide a guide
to Python Programming. Instead, this book is specifically
about debugging Python with Anaconda’s Spyder application.
The concepts around Python debugging apply equally to
other environments, but the screens and debugging tools
may vary slightly.
You may wonder why I’ve included Python Basics in
Chapter 3. I found it difficult to explain an IndexError without
first explaining data structures and their indexes. Similarly, a
Dictionary KeyError doesn’t mean much without an
understanding of a Dictionary. Syntax errors are fairly
obvious in Spyder, but it doesn’t hurt to have a brief
explanation of the syntax the parser expects.
Finally, Chapter 6 demonstrates how to view values,
types, and the length of objects. Since the syntax varies by
the type of object, I wanted to provide a reference with the
exact syntax for each object type.

1.3 What’s Next?


The next chapter walks you through installing Anaconda
and the basic Spyder environment. We’ll also look at an
overall plan for debugging code.

25
2. Debugging Overview

In this Chapter we discuss


Plan for Debugging
Start Small
Keep Multiple Versions of Your Code
Intended Outcome
Test Data Files
Plan for Tomorrow
Experiment
Divide and Conquer
The Debugging Environment
Python
Anaconda & Spyder
Help
What’s Next?

Writing code begins with your vision of what the program


should do. You write code, see what happens, and make
changes along the way. When the code doesn’t do what you
want, debugging helps you zero in on what’s happening while
the code runs. In essence, you can pause program execution
and “freeze” your program at that point in time, looking at
variable and object values at that moment.

26
This Chapter outlines a few suggestions to approach
programming and debugging. The Examples in Chapter 7
follow a similar methodology.
Intended Outcome : What I wanted the program to do.
Actual Result : What the program did.
Incorrect Code : A look at the code before any changes.
Debugging Experiment : What I suspect is wrong with the
program, and the steps I tried to “debug” what the program
is doing.
How to Resolve the Issue : A brief description of the
change to the code to achieve my “Intended Outcome.”
Correct Code : The finished code that works as I intended.

2.1 Plan for Debugging


Programming is not my primary job. Instead,
programming is a tool I use for data mining or organizing
projects. A day in my programming life includes lots of
interruptions. It may be weeks or months before I pick up a
project and continue coding. For this reason, I’ve adopted a
few suggestions from programming friends to make my life
easier.

1. Work on small chunks of code, test, and then move on to


the next piece.
2. Keep multiple backup versions of your files.
3. Have a clear idea of what you want your program to do.
4. Use small data file samples that you know have clean

27
data to develop your code. When you’ve tested your code
and are confident there are no bugs, use live data
connections or real data files.
5. Keep notes of where you stopped programming and the
next steps.

Start Small
Write small chunks of code. Test and validate that piece
of code, then move on. This “Correct Code ” is also a good
baseline for backups.

Keep Multiple Versions of Your Code


Keep multiple backup versions of your files. My backup
files often include the date and time in the filename. That
way, if I really mess up the code, I can easily go back to the
“Correct Code ” that worked earlier today or last month.

Intended Outcome
While I’m not suggesting you have a vision statement for
your program, it doesn’t hurt to have an “Intended
Outcome ” of what you’re trying to accomplish. This
synopsis is beneficial in several ways:
• Pair programming, or asking for another opinion.

28
• When you check-in your code to a source control
program.
• During peer review.
• In a Sprint Review, where you demonstrate your
program to others.
In case you reach out to another programmer for
assistance, share as much information as possible.

1. The incorrect code. If you have the last working version


of your code, that might also be helpful.
2. Your Debugging Experiment methodology, and what
you’ve already tried.
3. The “Actual Result.” What happens when you run the
program?

Test Data Files


Web scraping and external data files can be messy and
huge. Take a moment to familiarize yourself with samples of
the live data or data dumps. Make small “test data files” or
mock-ups of the data. Scrub the data to ensure it’s clean.
If you plan to code for blank data, hidden characters, or
type conversions, set aside a version of the data for that
purpose. Initially, keep the test data as simple as possible.
Use these test data files to save time iterating through
thousands (or millions) of rows of data.
Look for hidden characters and blank cells or data
elements. Make notes of data types and other issues as a
reminder to add logic to your code to handle the data
correctly.

Often, when you dump database data to a CSV or Excel

29
file, there is an error when you try to open the file. For
example, if you open an Excel file, it may prompt you to
“fix” the data on file open.

Chapter 4 has an example of a mock-up HTML data file in


the topic “Create Test Data.”

Plan for Tomorrow


When you’re done for the day or decide to take a break,
leave a note for yourself of where you stopped. Include what
is or is not working and what you want to do next.
Review your pseudocode and Intended Outcome to be
sure you’re on the right track. Pseudocode is an outline of
your program design in simple terms, often written in plain
English. These types of notes remind me of where I left off
programming and what I need to work on next.

2.2 Debugging Steps


In some ways debugging is more of an art than science.
Since I’m analytical, I am more inclined to use the scientific
method for my debugging. It’s really up to you to decide on
your style of debugging, and if you’ll use any of these
suggestions.

1. When debugging, keep a logbook of your experiments, so


you know what you’ve already tried.
2. Divide and conquer. Divide the code in half and test each
half to see which part has the error. Repeat these steps
to drill down to the location with the error.
3. Make a backup of your files before starting your
experiments.

30
4. Start with a clear Problem Statement of the defect.
5. Don’t believe everything you hear. If the original defect is
the program works with Oracle data and not Cassandra
data, verify that is really the case.
6. Examine the environment.
7. Create a list of possible suspects.
8. In case you’re out of ideas and haven’t found the defect,
take a break. Work on something else, go for a walk or
come back to the problem tomorrow.

Logbook
Keep a logbook of your debugging experiments. Write
down the steps and outcome for each task. I find writing
down my issues frees my mind from worrying about the
problem, and allows me to brainstorm at my leisure.

Divide and Conquer


When debugging, pick a logical point to divide the code in
half. Use a process of elimination to drill down to the error in
the code.

1. Divide the program into Part 1 Code and Part 2 Code .


2. Run Part 1 Code . If there are no errors, you know that
Part 1 is working. If you have errors, divide Part 1 Code
again. Repeat the process until you drill down to the root
cause.
3. If Part 1 Code ran without errors, run Part 2 Code . If you
find an error, divide Part 2 Code and repeat the steps.
Wherever possible, eliminate the code that is unrelated to
the error. Chapter 4 has an example of skiping unrelated

31
code in the topic “Focused Testing.”

Backup Files Before Debugging


Create a backup of your files before you change anything.

Problem Statement
Develop a clear problem statement with as much detail as
possible. Who can you contact for more details? When
determining how critical the issue is, consider the impact to
business and if there is a workaround.

Doubt Everything
Verify the accuracy of the original defect report by
recreating the issue yourself.

Look Around Your Environment


Before creating a list of possible causes, gather
background on the environment.

1. Has the program ever worked?


2. When was the last time the program ran successfully?
• Did it work last month?
• Is this the first time it ran on a Monday or on the first
day of the month?
• Is there heavy load on the environment because it’s the
end of the month or quarter?
3. Can you connect to devices outside of the program

32
successfully? Can you query the Cassandra database
outside of your program? Is the web server responding to
requests? Is one of the integrated systems down?
4. Did the program encounter an Out of Memory error?

Create a List of Suspects


As a starting point for your experiments, make a list of
components that could be causing the defect.

• Your app
• The last few lines of code you changed
• Python language
• OS
• Connection to a web page
• The format of a database table or web page changed
• More than one library with the same name in different
paths
• One of your script files with the same name as a library

What Do You Think is the Cause?


Chances are, at this point you have some idea where you

33
want to start investigating. Make a list of your ideas or
hypothesis of what might be wrong.

Refine Your Experiment


As you refine your Debugging Experiment , you’ll
probably notice parts of the code that you don’t need to test.
Your goal is to narrow the search by removing things that
don’t contribute to your hypothesis. Chapter 4 has an
example that narrows your search in the topic “Focused
Testing.” Modify your program to temporarily eliminate these
items from your experiment. Consider hard coding values or
using temporary mock-ups of data.

Experiment
Change one thing at a time, and observe what happens.
Please, write everything down in your logbook, noting each
step and the outcome. The simple act of writing down my
experiment forces me to pause and consider what happened
and why.
• What steps did you take?
• What did you expect to happen?
• What actually happened?
Review the experiment and see if you can come up with a
theory about the cause of the defect.

34
• Is there something you should not see?
• Do you need to refine your experiment further?
• Do you have a theory about what might be causing the
defect?
• Do all your test results fit in with your theory, or is there
one result that doesn’t quite fit? Don’t ignore the evidence
that contradicts your theory. If you you aren’t sure how
that piece of code works, dig into the code because that
might be where the problem lies.

Keep a log of the things you’ve tried as you debug your


program, to avoid repeating the same tests.

Success at Last
The last experiment you conduct that unequivocally works
is the fix. The program does what you want, and you reach
your “Intended Outcome .”

2.3 The Debugging


Environment
For this book, I am using the Anaconda Distribution that
includes the Spyder application. My Anaconda programs
support Python 3.7.

35
Python
Python is an open-source (free) programming language
for Web Development, GUI development, Scientific and
Numeric data science, Software Development, and System
Administration. The examples use the open-source Anaconda
Data Science Distribution that includes Python version 3.7.
Spyder, the Scientific Python Development Environment,
comes with Anaconda, and I run Python scripts in Spyder
primarily on a Windows machine. For variety, I’ve also
included several examples on a MAC computer.
In this Chapter, we’ll install Anaconda and set up your
environment. If you are familiar with Python and want to
jump into debugging, feel free to skip ahead to Chapter 4.

Anaconda
Download the Anaconda Distribution that includes Python
version 3.7. Other Python versions may vary slightly
compared to the examples in this manual. When prompted,
update your path settings. The install takes a while, so you
might want to grab a cup of coffee or something.

Spyder
Spyder is an Integrated Desktop Environment or IDE.
Spyder includes an Editor, Console or Spyder Shell, Variable
Explorer, Help module, and other tools. These modules are
displayed in “Panes” in Spyder.
On a Windows machine, launch Spyder from the Start
Menu, in the Anaconda folder. On a MAC computer, open the
Anaconda Navigator and launch “Spyder.”

36
The Spyder Default Layout has three panes, as shown
below. You can return to this layout at any time from the
View menu under Windows Layouts. You can close or open
other panes to suit your preferences.

Figure 2.1 Project Files

1. The Editor window is where you type your code and


create your script files.
2. The Help window displays syntax, function help, and
more.
3. The iPython Console or Python shell. When you start
Spyder the Console prompt is In[1]: .
When you click “Run,” the results are output to the
Console. When you type a command in the Console,
Python immediately runs the command. The Console is
useful when debugging, or experimenting with different
statements for your code.
Results displayed in the Console include code output and
error messages. For example, if you use the print()
method, the results are output to the Console window. In
the example below, the Console displays “ Welcome to
Project1.1.py .”

37
Figure 2.2 The iPython Console

Run a Script or Program


With Spyder open, click on the File menu and then click
on “Open” and open, or create, a script file. In the next
example, the “Project1.1.py ” file is open in the Editor.
Click on the green arrow or use the Run menu, as
shown below.

Figure 2.3 Run the Program

In the Run menu select “Run selection or current line”


to run only the selected lines of code.

In the next figure, I have two panes open. The Editor is

38
on the left, and the Console window is on the right. Initially,
the Console window displays the prompt In [ 1 ]: . After I
click “Run ,” the Console window changes, as shown below.
The first output line displays the name of the program file
and the working directory.

In [ 1 ]: runfile( ‘C:/Python_lab1/Project1/Project1.1.py ’, wdir=’


C:/Python_lab1/Project1 ’)
Welcome to Project1.1.py
In [ 2 ] :

Figure 2.4 The Console

2.4 Help
In Spyder, click on the View menu and click “Panes” to
open the “Help” pane. Now, click on the Help menu and click
on “Spyder Tutorial.” The tutorial opens in the Help pane.
The topic “Recommended first steps for Python beginners” is
an excellent resource for new programmers.
Chapter 4 demonstrates Debug Mode , Interactive Mode ,
and Variable Explorer. These tools look at your code while it’s
running, in effect, “debugging.”
To open Help for an object, place the cursor on an object
name in the Editor , press Ctrl-I, or Command-I on a MAC.
Help inspects the object and gathers docstring information.

39
2.5 What’s Next?
Your Lab environment is now setup. Let’s move on to
Chapter 3 and review a few basic Python language
guidelines.

40
3. Python Basics

In this chapter we discuss


Statements
Python Syntax
Objects
Immutable Objects
Variables
Types of Data
Numbers
Strings
Introduction to Data Structures
List
Tuple
Dictionary
Set
Comparison Operators
Control Statements
Indented Code (a Suite)
Functions & Methods
Classes

Now that your environment is set up, we’ll take a brief


look at a few basic Python concepts. Syntax and runtime
errors often involve incorrect syntax, indentation errors, or a
mismatch in object types. This chapter is by no means a

41
complete Python language guide; instead, think of it as an
abbreviated part of the Python language documentation. I
need this small subset of information to demonstrate how
you will refer back to the Python documentation as you
debug your program. The “Appendix - References” at the end
of this book has links to the Python documentation related to
these topics.

3.1 Statements
The actions that a program takes are called “statements.”

3.2 Python Syntax


The Spyder Integrated Development Environment (IDE)
includes an Editor that warns you when you have a syntax
error in your script. A yellow triangle on the left side of the
Editor pane next to the line number indicates an error. Next,
we’ll look at a few common causes of syntax errors.
• Valid characters for variable names and identifiers vary
between Python 2.x and Python 3.x. Python 3 added
support for Unicode characters in PEP 3131 to
accomodate programmers who are not familiar with the
English language. To avoid errors, I adhere to these
guidelines.
• Identifiers begin with a letter.
• Numbers are allowed in object names, except as the
first character. Object names are also known as
identifiers.
• In Python 2.x, the only special character allowed in an
identifier name is an underscore. Instead of spaces in

42
identifier names, try an underscore. Illegal spaces can
cause a syntax error.
• The PEP 8 Style Guide suggests lowercase characters for
identifier names and functions. Classes begin with an
uppercase letter. For example, variables and list names
are lowercase.
• Python is case sensitive. There is a difference between
“myString” and “mystring.” The Python Interpreter
displays a NameError when there is a misspelled
identifier.
• When defining a function or control statement, the line
should always end with a colon.
• A data structure name should be plural, and items in the
data set should be singular. For example, a List named
“vacations” with List items: vacation[0], vacation[1], etc.
• Do not use reserved keywords as identifiers. A missing
keyword causes a SyntaxError.
• Unpaired parentheses cause a SyntaxError.
• An empty Suite (indented block of code) is illegal. See
“Indented Code (Suite)” or Example 7 for more
information.

Python has reserved keywords like “global” or “try.”


When you use a keyword as a variable name, it causes a
syntax error.

These Chapter 7 examples illustrate a few syntax errors:


Example 7
Example 8
Example 9
Example 10

43
Example 11
Example 12
Example 16

3.3 Objects
An object is a collection of data. Everything in Python is
an object. Objects have an identity, type, and value. The
“identifier” or “identity” of the object is the name of the
object. With the library “openpyxl ,” you assign objects to
both the workbook and worksheet, and then you use those
objects with methods to read or update values (the data).
from openpyxl import load_workbook
wb2 = load_workbook (aftfile, data_only = True)
ws2 = wb2[“ ExportedData ”]

3.4 Immutable Objects


Python string and number types are immutable, which
means the values can not be changed. You can not change
an existing string/int/float, but you can create a new string
with changed data.
If you’re new to programming, this concept may seem
strange. Take the case of a Python object of the type “int .”
The code statement bfr = bfr + 1 seems to change the
value of bfr . In reality, this statement creates a new object.
The new object has a new identifier and a different location in
memory. To see this in action, run this code in the Console
to see the identifiers for the bfr objects.
print( id (bfr))
bfr = bfr + 1
print( id (bfr))

44
Immutable objects are quicker to access, and this
improves code performance. Another advantage of
immutable objects is understandability, and knowing the
object will never change.

3.5 Variables
Think of a variable as a container to store values. When a
program runs, the value inside the variable may change. A
letter or number is a value. An assignment statement
creates a variable and assigns a value, as shown below. The
left side of an assignment statement must be a variable.
mynumber = 2000000

The Python style guide suggests that variable names


begin with a letter.

3.6 Types of Data


Python has several types of data. Text, numeric, and
sequence (list/tuple) are some of the built-in data types. The
following table has a few of the basic data types. Data
structures include lists, tuples, sets, and dictionaries.

45
Type Description Assignment Value
int integer my_var=3 3
str string of characters my_var2=‘Hi’ Hi
float floating-point number my_var3=3.85 3.85
bool boolean (true/false) my_var4=false false

Table 3.1 Data Types

46
When my_var = 3, the statement float(my_var+5) returns
8.0 .
When my_var = 3, the statement print(34//my_var)
returns 11 .

What is the Data Type?


If you’re unsure of the data type, the type() function
displays the type of data.
print(type( my_var) )

Converting Data Types


When working with data, you may need to change or
convert the data type. For example, during a calculation, you
may want to convert between a float and an int to remove
decimal places. When concatenating numeric values and
strings, you would convert the integer value to a string with
the statement str(my_int ).

int(my_var)
str(my_var)
float(my_var)
bool(my_var)

The ‘ None’ Value


In Python the absence of a value is called “None” which
must be capitalized. In other languages this would be a null
value. When a function has no return statement, it returns a
value of “None.” When working with external data sources
you may have to account for this type of value, as shown in

47
Example 17. An “if statement” that tests for a value of
“None” is shown below.
if myvar is not None:

3.7 Numbers
When assigning integer values, do not use commas.
Python interprets 2,000,000 as three integers separated by
commas.
mynumber = 2000000
In the previous example, I assign 2000000 to the integer
variable “mynumber .” For readability, you can add
underscores as a separator.
mynumber = 2_000_000

3.8 Strings
A string is a sequence of characters. To assign a value to
a string variable, use single quotes, as shown below. Strings
are immutable and can not be changed. To assign a value to
a string, use the same syntax and, in effect, create a new
string variable with the same name.
mystring = ‘books’

3.9 Introduction to Data


Structures
There are four built-in data structures in Python. In this
book, we’ll primarily look at Lists, Tuples, and Dictionaries.

48
• List
• Tuple
• Dictionary
• Set

3.10 List
A list is an ordered collection of values of objects. Lists
are usually of the same type, but can be a combination of
types. A List is similar to an array in other languages. List
values are mutable; the values can change. The list can grow
or shrink as needed. A unique index (a number or name)
refers to each list item. When creating Lists use square
brackets [ ] . The index is used when updating list items.
ws1 = wb1[“ ExportedData ”]

Python starts counting at 0 . The first item in a List has


an index of 0 , and the second item has an index of 1 .

When creating a List, use brackets [] . A List can have


heterogeneous data; meaning Lists can have different data
types. Commas separate items.

49
Description Syntax Comments
mylist = [‘a’, ‘b’,
Create a List and assign values
‘c’]
Create a List and assign number values mylist2=[1,2,3 4]
Assign a value to the first item in the
mylist2[0] = 8
List
Access the value of the List item mylist2[1] Returns the value of the first item in the List
Use negative index numbers when counting from the
Access the value of the last List item mylist2[-1]
right
Return all items in a List mylist

Table 2.1 List Objects

Iterate Through Items in a List


A “for loop” is one option to iterate through items in a
List, as shown below.

for j in mylist:
print(‘mylist item is:’, mylist[j])

These Chapter 7 examples illustrate a few List errors:


Example 1
Example 2
Example 3

3.11 Tuple
A tuple is similar to a list and is immutable. Immutable
objects can not be changed. Tuples use parentheses ( ) and
can have heterogeneous data, meaning Tuples can have
different data types. Items are separated by commas. Only
immutable elements are Dictionary keys, so only Tuples can
be used as Dictionary keys. Lists are mutable and can not be
used as Dictionary keys.

50
Tuple indices must be integers or slices, not a string.

51
Description Syntax Comments
Create a Tuple and assign values mytuple = (‘a’, ‘b’,
to 4 items ‘c’, ‘d’)
Create an empty Tuple mytuple = tuple()
mytuple2 = Notice the comma at the end to instruct Python this is a
Create Tuple with one item
(‘Rachel’,) Tuple and not a String.
Assign number values to several
mytuple3 = (1, 2, 3)
Tuple items
Assign a value to the first item in mytuple4[
The first item in the Tuple has an index value of 0.
mytuple4 0]=’Apple’
View the value of the 2nd Tuple In {1]: mytuple4[1]
The Python Interpreter returns the value Orange .
item Orange

Table 2.2 Tuple Objects

Iterate Through Items in a Tuple


A “while loop” is one option to iterate through items in a
Tuple, as shown below.
mytuple4 = (‘Apple’,‘Orange’, ‘Watermelon’)
j=0
while j < 3 :
print(‘my fruit is:’, mytuple4[j])
j+= 1

A “for loop” is another option to iterate through items in a


Tuple. Indices must be valid integers. The two samples below
are valid and do the same thing.

mytuple4 = ( 0 , 1 , 2 )
for k in mytuple4:
print(‘my number is:’, k)

mytuple4 = ( 0 , 1 , 2 )
for k in mytuple4:
print(‘my number is:’, mytuple4[k])

The sample code below is invalid and causes an

52
“IndexError ,” because there are only three objects in the
Tuple with values 1, 2, 3. Python starts counting at 0. The
print statement is using “mytuple4[k] ” or mytuple[1],
mytuple[2], and mytuple[3]. When you run the program, the
Python Interpreter warns that “3 ” is not a valid index.

mytuple4 = ( 1 , 2, 3 )
for k in mytuple4:
print(‘my number is:’, mytuple4[k])

3.12 Dictionary
A Dictionary is an ordered set of key/value pairs.
Dictionaries are often depicted as two columns, with the list
of keys in the first column, and values in the second column.
Only immutable elements can be used as Dictionary keys, so
while Tuples can be used as Dictionary keys, Lists are
mutable and can not be used as Dictionary keys.

53
Key Value
Name John
Age 32
Height5.10”

Table 2.3 Sample Dictionary


A Dictionary is unordered and can grow and shrink as
needed. When creating Dictionaries, use curly braces {} .
The key is followed by a colon : and a paired value. In the
example below, the first key is ‘Name,’ and the value is
‘Zimmerman .’ The second key is ‘Grade,’ and the value is
‘A .’ A comma , separates the key pairs.

Create a Dictionary
To create a Dictionary with three key pairs, use the
following syntax. For readability, the key pairs are usually
written in this format.

mydictionary= { ‘Name’ : ‘Zimmerman’ ,


‘Grade’ : ‘A’ ,
‘Course’ : ‘Python Programming’ }
To create an empty dictionary type
mydictionary = { }

Assign a Dictionary Value Using the


Key Name
To update a Dictionary value use the following syntax.
mydictionary[‘Name’]: ‘Smith’

54
Add a New Key to an Existing
Dictionary
To add a new key, ‘Credits’ to an existing Dictionary, use
this syntax.
mydictionary[‘Credits’] = ’3’

Iterate Through Key-Pairs in a


Dictionary
This “for loop” returns the key-pairs in the Dictionary. The
first line in this example creates two variables “mykey” and
“myvalue” for the key-value pairs. The method items()
returns a list of the key-value pairs.

for mykey, myvalue in mydictionary.items():


print(“\pKey: ”, mykey, “\tValue: ”, myvalue )

Figure 3.1 Print Key-Value Pairs

Iterate Through Keys in a Dictionary


This “for loop” returns the Keys in the Dictionary. To
make your code easier to read, add the keys() method to the
same statement.

for mykey in mydictionary:


print(“\pKey: ”, mykey )

55
The next example is the same statement with the keys()
method.

for mykey in mydictionary.keys():


print(“\pKey: ”, mykey )

Access the Value of a Dictionary


Item
This example uses the Console to display the value of the
key “Name.” The Python Interpreter returns the value
“Zimmerman” to the Console pane.

In [ 1 ] : mydictionary[‘Name’]
Zimmerman

In this next example, I modified the previous code that


returned the keys in the Dictionary. Here I use the title()
method to access the Dictionary values.

for mykey in mydictionary.keys():


print(mykey, “:” , mydictionary[mykey].title())

Another way to access Dictionary values is with the


values() method, as shown below.

for myvalues in mydictionary.values():


print(myvalues.title())

3.13 Set
A Set is unordered objects and contains no duplicates. A
Set grows or shrinks as needed. When working with Sets,
there are functions to perform Unions, Intersections, and find

56
Differences. When creating a set, use curly braces {} and
separate items with a comma. The second row in the table
below creates a set with one item. Notice the line ends in a
comma, to indicate to Python this is a Set and not a String.

57
Description Syntax Comments
Create a Set and assign values myset = {‘a’, ‘b’, ‘c’}
Create a Set with one item myset2 = {‘John’,}
Create an empty Set myset3 = set()
Create a Set and assign values myset3 = set(‘abc’) With set() function

Table 2.4 Creating Sets

3.14 Comparison Operators


Use Comparison Operators to compare two values or for
membership test operations.
Operator Description Type
> Greater than Values
< Less than Values
>= Greater than or equal to Values
<= Less than or equal to Values
== Equal (values) Values
!= Not equal Values
is Equal (boolean) Boolean
is not Not Equal (boolean) Boolean
in Test for membership
not in Test for membership

Table 2.5 Comparison Operators

3.15 Control Statements


Python control statements control the flow of the
program. Examples of control statements are For, While, If,
and Else. When the control statement is true, the indented
lines that follow run.
The control statement always ends with a colon, and you
indent the next line of code to the right. If you want to run
several lines of code as part of the control statement, the

58
lines are all indented to the same level.
The first line of the control statement, and all the
indented lines that follow, is called a “Suite” in Python. Other
programming languages often refer to this structure as a
block of code.
A control statement moves through items in a data
structure. When this program runs, each time the program
loops through the code, the next item in the list is displayed.
fruits = [‘Apple’,‘Orange’, ‘Watermelon’]
for fruit in fruits:
print(‘my fruit is:’, fruit)

An iteration variable can also be used to iterate list items.


For example, when the variable “i” is a number with a value
of “0.” The first time the loop runs list[i] refers to list[0]. The
next time the list runs, list[i] refers to list[1].
fruits = [‘Apple’,‘Orange’, ‘Watermelon’]
for i in range( 3 ):
print(‘my fruit is:’, fruits[i])

In Chapter 7, Example 20 demonstrates a “for” control


statement. Example 6 demonstrates a “while” control
statement.

3.16 Indented Code (a


Suite)
In the next figure, there is a red box around the code
from line 28 to 48. I added a red vertical dotted line to
highlight where the code is indented. This is a Suite of code.

59
Let’s look at the code on lines 29, 30, 31, 32, and 48.
These lines are all indented to the same vertical level. This
code Suite, or block of code, begins on line 28. The last line
in this code Suite is line 48.

60
Indentation in Python scripts defines a “Suite” or code
block.

In this example, the shaded Suite (block of code) is a


second “while loop” (lines 34 to 46.) This second Suite is
“nested” because it is inside the first Suite. Within the nested
Suite, line 38 only runs when the if statement on line 37
evaluates to “true .” A nested if statement means there is a
second “if statement” within the first if statement.
In this example, the “bfr ” counter on line 48 is the last
line in this Suite and, in effect, moves forward in the loop to
the next item.

61
Figure 3.2 An Indented “Suite” or Block of Code
In Python, an empty Suite (indented block of code) is
illegal. For example, an “if statement” that does nothing is
illegal. Instead, use the “pass” function when your code
should take no action, as shown in Chapter 7, Example 7.
These Chapter 7 examples illustrate a few List errors:
Example 1
Example 2

3.17 Functions and


Methods
Functions are a sequence of statements. When you
define a function within a class, it is called a method . First,
you define a function. Once a function is defined, you can use
it as many times as you like by calling the function.
1
def menu (meal, special=False):
2

Depending on whether you are defining or calling a


function, you call the items in parentheses either
“parameters” or “arguments.” When defining a function, the
items in parenthesis are parameters . When calling a
function, the items are arguments .

62
Defining a Function
When defining a function in the Editor , the parameters
in parentheses specify what types of arguments (values) the
function can accept. In my earlier example, the parameter
“special” assigned a default boolean value of “False.” The
“special” parameter has a type of “boolean.”
def menu (meal, special=False):
1 msg = ““
2 if special is True:
3 msg = ‘The specials today are
4 Mimosas. ‘
5 if meal == ‘breakfast’:
6 msg = ‘Breakfast is eggs and
7 toast. ‘
8 else :
9 msg = ‘Sorry, we ran out of food.

return msg

The parameter “meal” has no default value. Because of


Python’s dynamic typing, when calling the function, I can
pass any type of data for “meal.”

The Python style guide recommends function names


begin with a lowercase letter. Class names should begin
with an uppercase letter.

The Chapter 6 topic, “The Function Call Signature ,”


explains how to view the parameters accepted by a function.
In Chapter 7, Example 20 uses the signature function to
retrieve parameter information.

Parameters
In this example, there are two parameters in the function
definition, “meal” and “special.”

63
Parameter Name Default Value Required/Optional
Positional meal Required
Keyword special False Optional

Table 2.6 Parameters

Arguments
Arguments are the values you pass to a function when
calling the function. Not all functions have arguments. In this
example, the function has two arguments.

64
menu (‘breakfast’, special=True):
Parameter Argument
Order
Name Value
1 meal breakfast
2 special True

When I call the this function, the parameters are now


referred to as “arguments” because I am calling the function.

Keyword Arguments
The second parameter in my function definition includes
the keyword “special” with a default value of “False .” When
calling a function, a name precedes the keyword argument.
List keyword arguments at the end of the parenthesized list,
after positional arguments. In this example, the keyword
name is “special.”

Positional Arguments
The “meal” argument is a positional argument because it
does not have a keyword. List positional arguments before
any keyword arguments.
The example below is invalid because a positional
argument is after a keyword argument.
def menu (special=False, meal):

Optional Arguments
Because “special” has a default value, when calling the
function, “special” is an optional argument. If you don’t
provide the argument when calling the function, Python uses
the default value “False .”

An Arbitrary Number of Arguments


Occasionally, you may need to set an arbitrary number of
arguments for a function. Let’s say you have a function to
print personalized movie tickets for each patron. The patron
names vary from day-to-day. In the next code example, on

65
line 1, there are two parameters enclosed in parenthesis:

66
def print_tickets(number_of_tickets, *name):
1
i=0
2
while i < number_of_tickets:
3
print(name[i])
4
i += 1
5
print_tickets(3 , ‘Carter’, ‘Rachel’,
6
‘Michael’)

Line 1 includes an asterisk * to indicate there are an


arbitrary number of name arguments (values) passed to the
function.

number_of_tickets
*name
When I call the function on line 8, I pass it four values or
arguments. Three of the arguments are names.
print_tickets(3 , ‘Carter’, ‘Rachel’, ‘Michael’)

How to View the Function Argument Definition


To view arguments accepted by a function or method,
you can use the Help() function, or inspect the function’s call
signature . For example, to see the arguments of the meal()
function, run the program to create the function. In the
Console import the inspect library, and type the print
statement shown below. The Python Interpreter returns the
parameters for the menu function.

67
In [3]: from inspect import signature
In [4]: print(str(signature (menu)))
(meal, special=False)
In [5]:

Calling a Function or Method


When calling a function, you pass arguments with values
to the function. Continuing with my example, the last line
calls the function “menu .”
print(menu(‘breakfast ’))
def menu (meal, special=False):
1 msg = ““
2 if special is True:
3 msg = ‘The specials today are
4 Mimosas. ‘
5 if meal == ‘breakfast’:
6 msg = ‘Breakfast is eggs and
7 toast. ‘
8 else :
9 msg = ‘Sorry, we ran out of food.
10 ‘
return msg
print(menu(‘breakfast’))

The two statements below call the “menu” function and


produce the same result. In the second example, I omit the
optional argument. When calling the function, the parameter
“meal” is referrred to as an argument that has a value of
“breakfast .”
menu(‘breakfast’, special=False)
menu(‘breakfast’)

In Chapter 7, Example 6 illustrates an AttributeError


caused by missing keyword names when calling a method.

Function Return Value


A function returns one object, but that object might be a

68
container like a tuple with several items. When a function
doesn’t specify a return value, it returns the special value
“None. ” For debugging purposes, let’s look at the function
return object in terms of:

• What type of return object does the function return?


• Does the function return a value of “ None ?”
• Does the function return a tuple with several items?

All Paths Do Not Have a Return Value


Previously, the example function returned a value on line
9. A return value must exist for all paths through the
function. In the next example, I modified the program to
have different return values for several paths. The “if” suites
of code on lines 5 and 8 both have return values.
def menu (meal, special=False):
1 msg = ““
2 if special is True:
3 msg = ‘The specials today are
4 Mimosas. ‘
5 return msg
6 if meal == ‘breakfast’:
7 msg = ‘Breakfast is eggs and
8 toast. ‘
9 return msg
10 else :
11 msg = ‘Sorry, we ran out of food.

print(menu(‘lunch’))

Do you see the problem with my code? The “else” suite of


code beginning on line 9 does not have a return value. When
there is no return value, the Python Interpreter returns the
value “None ,” which may not be what you wanted. The
topic “Does the Object have a Value of None” in Chapter 6
explains the pitfalls of the value “None .” Example 17 in
Chapter 7 illustrates how to identify a

69
More than One Return Value
Occasionally, functions return more than one value. For
example, a function may return a tuple or list. In the next
example, I pass the function’s return values to mytxt .
Because the function returns two values on line 10 in a tuple,
the Console displays an error.

70
Figure 3.3 Multiple Return Values
To fix my program, I need to change line 17 to print each
element in the “mytxt ” tuple, as shown below.
print (mytxt[0 ], mytxt[1 ])

The Type of Return Value


The type of return value is especially important if you’re
using it as the argument for another function. For example,
the “print” function expects a string, and my “menu ”
function returns a tuple. In this case, the Python Interpreter
displays a TypeError. Using the previous function as an
example, in the Console I could use the function “type” to
identify the type of object the “menu ” function returns.
In [1]: type(menu(‘lunch’))
Ou t [1]: tuple

To resolve this error, I use index notation to reference a


particular item in the “mytxt ” tuple returned by the “menu”
function.
print (mytxt[0 ], mytxt[1 ])

3.18 Classes
This topic provides a brief overview of classes. The
docs.ptyhon.org website has a tutorial on classes and
explains the concept of “self” in great detail.

71
• Create a Class
• The DocString
• Variables - Attributes
• Create an Instance of the Class
• Methods
• Dotted Notation for Attributes
• Calling a Method

72
class Car():
“””This class represents a car.”””
1 yr = 2020
2 def __init__(self , model, make, year):
3 “””Initialize model, make, and year
4 variables.”””
5 self .model = model
6 self .make = make
7 self .year = year
8 def drive(self ):
9 “””Move the car.”””
10 print(self .model.title() + “ is now
11 moving.”)
12def parallelpark(self):
13 “””Parallel park the car.”””
14 print(self .model.title() + “ is now
15 parking.”)
16my_car = Car(‘Subaru’, ‘Crosstrek’, 2019 )
17print(my_car.model, my_car.make,
my_car.year)
my_car.parallelpark()

Create a Class
In this class example, the first line creates a class named
“Car.” Class names begin with a capital letter, to differentiate
them from function names which should be lowercase.

The DocString
Lines 2, 5, 10, and 13 look like comments, but are
actually examples of a “DocString.” The Chapter 6 topic, “The
Function Call Signature ,” explains how to work with the
“inspect” module and view a DocString signature.
The function help() reads the docstring when gathering
information about an object.

Variables - Attributes
Beginning with the function definition on line 4, you can

73
def __init__( self , model, make, year):
self
model
make
year
When working with the “my_car” instance of the Car
class, use dotted notation to reference the variables.

my_car.model
my_car.make
my_car.year
When referring to the state of an object, you are referring
to variables or data attributes . The variables model ,
make , and year on lines 6, 7, and 8, respectively, are
accessible through instances.
self .model = model
self .make = make
self .year = year
The statement below is invalid because there is no
attribute named “color. ” When I run this program, the
Python Interpreter displays an AttributeError in the
Console .
my_car.color
In Chapter 7, Example 6 illustrates an error with an
incorrect call for a class method, which causes an
AttributeError.

Instance Variables and Class


Variables
Instance variables are unique to each instance of the
class. For example, my_car.model is different than
my_car2.model . All instances of a Class share class

74
variables and methods. For example, all instances of the Car
class share the class variable “yr ” I created on line 3.

Create an Instance of the Class


Instantiation is when you create an instance of an object
from a class. On line 15, I create an instance of the Car class
named “my_car .”
my_car = Car(‘Subaru’, ‘Crosstrek’, 2019 )

Instance objects have attribute references. Valid attribute


names include “data attributes ” and “methods .”

Methods
A function that is part of a class is called a “method .”
When referring to the behavior of an object, you are
discussing the function or method. The “Car” class has two
methods, defined in lines 11 and 15. The “drive” method is
shown below.
def drive(self ):
“””Move the car.”””
print(self .model.title() + “ is now moving.”)

Dotted Notation for Attributes


The normal dotted notation “object.variable ” is used to
access the instance of the class (the object) and the
attribute. In this example, the syntax is “my_car.model .”
The primary object instance is “my_car ,” and the attribute
identifier name is “model .” To refer to the model, make, or
year attributes follow the syntax on line 21, as shown below.
print(my_car.model, my_car.make, my_car.year)

75
Calling a Method
To call a method in a class instance, use the syntax
shown in line 17.
my_car.parallelpark()

76
At the end of this book, the Appendix - Reference has
links for more information on Classes, Functions,
Methods, Attributes, and Instances.

These two statements call a method. The statement


syntax varies, but the statements do the same thing.
Car.drive(my_car)
my_car.drive()

3.19 Attributes
The Chapter 4 topic, “Variables and Objects in Memory ,”
discusses the current namespace and the concept of
attributes. The Python glossary entry for “attributes” is “a
value associated with an object which is referenced by name
using dotted expressions.”
In the Chapter 2 example, we looked at a line of code
with a number variable.
myint = 57
print(myint.upper)

When the program runs, it causes an unhandled


exception, and the Console Traceback message is
“AttributeError ,” because there is no attribute “upper” for
a variable of type “int.”
When looking at Classes in this chapter, we saw that
attributes could be variables or methods within a class
instance. In our earlier Class example, we saw that instance
objects have attribute references. Valid attribute names
include “data attributes ” and “methods .” In this example
of attributes, “yr ” is a class variable, and “drive ” is a

77
method in the my_car instance of the “Car” Class.

my_car.yr
my_car.drive

78
4. Debugging Tools

In this chapter we discuss


Debugging Overview
Add Print Statements to Your Script
Debug Mode
Variable Explorer
Example: Program Loops and Never Ends
Debug Commands
Interactive Mode
Introspection
Logging
The timeit() Function
Focused Testing
Create Test Data

This chapter outlines a few ways to use the Spyder IDE to


debug your program. With a few simple commands, there is
a wealth of information available about your variables,
functions, data structures, and more. We’ll look at:

• Adding Print Statements to code in the Editor, and viewing


the results in the Console (the Python Shell.)
• Using Debug Mode in Spyder.

79
• Using Interactive Mode in the Console .

4.1 Debugging Overview


When debugging code, I inspect values, types, function
arguments, and function return objects. “Introspection”
functions like help() and dir() also provide information on
methods, functions, and objects. There are also libraries for
“logging” and functions to identify bottlenecks and timing
issues. Finally, I’ll demonstrate how to focus on a specific
area of code for testing and how to create test data.
To begin, I’ll look at several ways to debug my code.

• Inspect Objects and Variables


• Add Print Statements to a Script
• Debug Mode
• Variable Explorer
• Interactive Mode
In the Editor, add print statements to your script, and
run the program. The Console , also known as the Python
Shell, displays the results of print statements.

In the Run menu select “Run selection or current line”


to run only the selected lines of code.

Run your program in Debug mode , stepping through the


lines of code. The Console prompt changes to ipdb in Debug
mode . In Debug Mode, you step through the lines of code,
pausing to look at the Variable Explorer pane or type
commands at the Console prompt, to inspect object values.
The Editor pane highlights the current line. This line
executes when you click “run current line” on the debug
toolbar. The Variable Explorer displays the values of each

80
variable in the current context.
Interactive Mode in the Console allows you to type
commands that display object values. In the Console type
the name, or identifier, of the object. The Python Interpreter
returns the value of the identifier. The object can be an
integer variable, a list item, tuple, or another type of object.
In the Console , you can also run individual lines of code
while developing or testing your code. Interactive Mode is a
great way to test code before adding it to your script. You
can also set a “breakpoint” to move to a particular location in
your program.

The topic “Variables and Objects in Memory” outlines


how Python creates variables and objects when you run
a program or script. If you type your object name in the
Console and the Traceback says “NameError,” insure
that you ran the line of code that creates the object.

4.2 Add Print Statements


to Your Script
A popular debugging choice is to add print statements to
your code. A print statement is a quick and easy way to
inspect an object’s type, value, and length, while your code is
running. Add a print statement to your script in the Editor
window, and on the Run menu execute your program. The
Console displays output from the print statement. The
Console is the Python Shell.
A quick and easy way to debug a program is to add print
statements to your code. In the next example, I added two
print statements to help me follow my running code.

81
1 meals = [‘breakfast’ , ‘lunch’ , ‘snack’ , ‘dinner’ ]
2 fruits = [‘apple’ , ‘orange’ , ‘grape’ ]
3 i=0
4 while i < 4 :
5 j=0
6 print (“my meal is: ” , meals[i])
7 while j < 4 :
8 print(“My choice of fruit is: ” ,
9 fruits[j])
10 print (“j is: ” , j)
11 j=j+1
12 i=i+1
In [1 ]: my meal is: breakfast
my meal is: breakfast
my meal is: breakfast
my meal is: breakfast
my meal is: breakfast
my meal is: breakfast
my meal is: breakfast

Try This 6.1 Print Statements


While marginally helpful, the print statements in the
Console window quickly scroll by because this program is in
an infinite loop. Scrolling output is where Debug Mode or
Logging comes into play, and we’ll look at both in the next
sections.
In Chapter 7, Example 15 uses print statements with
exception handling logic. Chapter 6 explores the syntax to
view an object’s type, length, and value.

Indenting Loop Print Statements


Another print option is “indenting” the print statements
each time the program loops through a Suite of code. In
Python, a “Suite ” of code is a block of indented code, as
discussed in Chapter 3. These print statements provide a
visual representation of how many times the loop has run.

82
meals = [‘breakfast’ , ‘lunch’ , ‘snack’ , ‘dinner’
1
]
2
fruits = [‘apple’ , ‘orange’ , ‘grape’ ]
3
i=0
4
level = ““
5
while i < 4 :
6
level = level + “.... ”
7
print(“my meal is: ” , fmeals[i])
8
i=i+1

In this example, the Console shows the print output with


a series of dots representing the depth of the loops. I use the
“level” string variable to create the effect.

Figure 4.1 Indenting Loop Print Statements

4.3 Debug Mode


Use the Debug menu commands to step through the
lines of code, or press Cntrl + F12 on a Windows computer to
move to the next breakpoint. The Variable Explorer displays
object values, changing over time as you step through the
program code.
In the Editor , double click on a line of code to set a
breakpoint or press F12 on a Windows computer. When
running a program in Debug Mode, a breakpoint pauses the
program at that point, so that you can inspect the variable
and object values. A red dot appears to the left of the line
number with the breakpoint.
On the Debug menu, select ‘debug’ to launch the iPython
debugger, or press Cntrl + F5 on a Windows computer. The

83
iPython debugger is active.

If a program halts and displays a Traceback error, you


can type %debug to start “Debug Mode.” Functions
that begin with the percent symbol are “magic functions
.”

In the next example, there is a breakpoint • on line 3. The


figure shows the Editor pane, as well as the Console pane
after I pressed Cntrl + F5 on a Windows computer to start
debugging. Notice the Console prompt changed to ipdb> .

84
1
mystring = “purple peanuts”
2
print (mystring)
3
In [1 ]: debugfile(‘C:/SampleScript.py’,
wdir=’C:’)
>C:\SampleScript.py(1)<module >()
---->1 mystring = “purple peanuts ”
2
3 print (mystring)
ipdb>
ipdb>

Table 4.1 Setting a Breakpoint


In the Console pane, an arrow indicates the current line
number, in this case, line 1. If Variable Explorer is not
already open, on the View menu select “Panes,” and then
click on Variable Explorer. As I “step-through ” the code, I
want to watch the “mystring” object in Variable Explorer. At
this point, the Variable Explorer is empty because we have
yet to run the first line of code.

As you step through the code, the Editor highlights the


current line.

Click the icon to Run the current line of code or press


Cntrl + F10 on a Windows computer. The Python interpreter
creates the object “mystring” and assigns the value “purple
peanuts.” This example of dynamic typing is one of the
reasons I love Python. With one line of code, Python figures
out the type of object to create and assigns a value.
In Chapter 7, Example 2 illustrates Debug Mode.

End Debug Mode


To exit the debugger, type q or quit at the Console
prompt and press enter, as shown below. If you are in an
iPython Session in the Console , you may have to press

85
enter several times to quit Debug Mode, or type Esc + Enter
. You can also restart the kernel when you select “Restart
Kernel” from the Consoles menu.
ipdb>C:\SampleScript.py(1)<module >()
1 mystring = “purple peanuts ”
2
---->3 print (mystring)
ipdb>
ipdb>quit
In [2 ]:
Table 4.2 Quit Debug Mode

4.4 Variable Explorer


Now, Variable Explorer displays a row with the type of
the “mystring” object, and the value I assigned in line 1.

Figure 4.2 The Variable Explorer Pane


Variable Explorer shows variables and objects in memory
. If you don’t see your object displayed in Variable Explorer,
you need to execute that part of the program. To start fresh,
in the Console use the magic command %Reset . See the
earlier topic “Variables and Objects in Memory.” In Chapter
7, Examples 1-3 demonstrate using the Variable Explorer.

4.5 Example: My Program


Loops and Never Ends
Let’s briefly look at an example of Debug Mode in action.
When I run this test program, it never ends. In other words,
it loops continuously. My hypothesis is the while loop that
begins on line 8 needs adjusted. First, I’ll stop the running

86
program. Next, I’ll use Debug Mode to step through the code
and identify what is happening.

1. On the Consoles menu, select “Restart Kernel” to interrupt


the running program.

2. Double click to the left of line 9 to add a breakpoint. A red


dot appears to the left of the line number.

3. On the Debug menu, select “Debug” or click on the Debug


control.

87
Figure 4.3 Add a Breakpoint
4. The Console prompt changes to ipdb> to indicate the
iPython Debugger is active, and the Variable explorer
displays values for the current active variables. Right
now, the variable cnt has a value of 1 .
The Console displays a few lines of the code, with an arrow
indicating the current line 9. Line 9 runs when I click on
“Continue Execution.”

The Debug Mode commands “u” or “up” move backward


in your program. These commands are useful to find
where the value was assigned to a variable.

5. When I click on “Continue Execution” again, line 9 runs


and loops back to line 8. The variable cnt still has a value
of 1 . At this point in the program, I wanted the value of
cnt to be 2.
If I use the command “Run Current Line,” in the Console
pane, I can see the program moving continuously from
line 8 to 9 and then looping back to 8. This program is in
an infinite loop.

88
Figure 4.4 Continue Execution

6. To resolve the issue, I need to indent line 11, so this


statement that increments the cnt variable is part of the
while loop. The concept of a “Suite” of Indented Code was
discussed in Chapter 3.
In the next figure, the output is correct in the Console .
In the Editor pane, you can see line 11 is now indented.

89
Figure 4.5 The Finished Program
To complete the program, I could add a print statement
with the answer to the riddle - the number one.
In Chapter 7, Example 1 demonstrates an infinite loop.

4.6 Debug Commands


In Debug Mode, type ? in the Console prompt ipdb> and
press enter to see a list of Debug Commands. A brief list of
popular commands is shown below.
ipdb> ?
For specific details on a particular command, type help,
and the command name. For example, type “help next .”

? Help with Debug commands


b or break Add a break
c Continue
cl or clear Clear breaks
d or down Move down in the stack trace
exit Exit Debug Mode
h or help Help on Debug Mode
j or jump Jumps to line number with a block of code
n or next Move to next line
u or up Move up in the stack trace

90
q or quit Exit Debug Mode

4.7 Interactive Mode


Another option to view object values involves typing in
the Console in Interactive Mode , which is similar to typing
in the Console while in Debug Mode. In the Console , type
the identifier (the name) of the object. The Python
interpreter displays the value in the Console , as shown
below.
In [ 1 ]: mystring

Out[1]: ‘purple peanuts’

You must run the program statement that creates or sets


the object value in the current namespace before the
Python Interpreter, or Variable Explorer, can display a
value.

While in Debug Mode , you can type the name of an


object in the Console , and the Python Interpreter displays
the value. This “Interactive Mode” also allows you to perform
calculations or use functions and methods, as shown in the
next example.
ipdb> mystring
‘purple peanuts’
ipdb> 2+3
5
ipdb> import math
ipdb> math.sqrt(16 )
4.0
ipdb>

Table 4.3 Type in Console While in Debug Mode


The iPython kernel also has several “magic commands”
that begin with the % character.

91
%debug
%reset
In Chapter 7, Example 1, Example 2, and Example 6
demonstrate Interactive Mode.

Increment Counters in the Console

One of my favorite debugging shortcuts is to change a


counter so that I can move forward when I’m looping through
the code. For example, I can change a “while loop” to move
from the 2nd iteration to the 1200th iteration. Let’s say I’m
in debug mode, and my program pauses at a breakpoint
where my “bfr” counter = 2. In the Console, I would
increment the “bfr” counter by typing bfr =1200 .

Watch Out for Changing Values


While most functions or methods provide useful results
when typed in the Console, you can get unexpected results.
In Chapter 7, Example 17 reads a TXT file with the OS
library. Readline() moves to the next line of the TXT file on
its own every time you type it in the Console, which may not
be what you were expecting.

iPython Session
The Console prompt changes to three dots and a colon
...: to indicate you are in an iPython Session . Press enter
twice, or press Esc + Enter , to exit the iPython session.

92
In [1 ]: def myfunction(str)
...: print(str)

When the newline prompt ...: is displayed, press Shift Enter to execute the
commands.

4.8 Introspection
Introspection is the ability to determine the type of the
object at runtime. Several functions help with introspection,
as well as the “ inspect ” library.

objectname ?
dir()
help()
id()
repr()
type()
To inspect objects, we’ll execute statements in the Editor
and Console , including statements with “Instrospection”
functions that provide details about objects. The syntax
varies depending on whether you are typing in the Editor or
Console pane. The syntax is also specific to the type of
object. We’ll look at those differences in depth in Chapter 6.
In the case of data structures like Lists, Tuples, or
Dictionaries, you may want to see values for the entire List or
the value of only a particular List item.

Editor

93
Console (Python Shell)

Variables and Objects in Memory


The Python Interpreter creates variables and objects
when you run a program or script. The collection of these
objects in the Console is the “ Namespace .” If you’re
debugging a line of code and a function uses an object, you
want to ensure the object exists in memory before trying to
view the object in Variable Explorer . The Variable Explorer
shows active variables in memory. Take, for example, this
line of code that uses a variable “myint ” of type “int.”
myint = 57
print(myint.upper)
If the program ran and created “myint” already, the
Console Traceback message is “AttributeError ,” because
there is no attribute “upper” for a variable of type “int.” If
the program hasn’t run and created the variable
“myint,” the Console Traceback message is “NameError. ”
In this example, a misleading Traceback message
“NameError” is hiding the Traceback message you want to
see, “AttributeError.”
When you change a function definition and want to use
the new version of the function, you can run just that part of
your code. In the Run menu select “Run selection or
current line” to run only the selected lines of code.

Use the %reset magic command in the Console to reset


the namespace.

Using ? in the Console


94
For details on any object, in the Console type the object
name followed by a question mark. For details on the object
“myfunction ,” in the Console type the function name
followed by a question mark, as shown below. The output
includes the Signature, DocString, and Type of object.
In [2 ]: myfunction?
Signature: myfunction(str)
Docstring: <no docstring>
File: ~/Python_Debugging/CODE/Ch 3 code/Functions/<ipython-input-8-df3069fd62ae>
Type: function

dir()
The function dir() displays all objects in the current local
namespace , as shown in the next figure. After running the
sample “Project1.1.py ” script, the local scope changes. This
script uses the “openpyxl” library to create the ws4 object.
For example, after running the “Project1.1.py script, the dir()
function displays relevant information about the program
objects in the Console . Type the dir() command in the
Console window.
In [2 ]: dir()

Figure 2.5 Objects in Current Local Scope


At this point, the function results aren’t exactly exciting.
Type dir(ws4) in the Console window to display attributes

95
specific to the ws4 object. The dir() function displays different
attributes depending on the type of object.
There is quite a long list of valid attributes for the ws4
object, and the next example only shows a few of the
attributes. In particular, I’m interested in what functions I
can use with the ws4 object, and I’ve highlighted the
“delete_rows ” method.
Note, if you’re using an older version of Python,
“delete_rows ” might not be available. The dir() function is
an easy way to check if a particular function or method
should work with your code.

Figure 2.6 Valid Attributes for the ws4 Object

help()
The Help() function invokes the help system for help with
a module, function, class, method, keyword, or
documentation topic. For example, when I type
help(load_workbook) in the Console window, Python
displays information specific to the method “load_workbook”
from the “openpyxl” library.
In [2]: help(load_workbook)

96
Figure 2.7 Help for load_workbook Method

The Inspect Library


Use the “Inspect ” library for additional information on an
object, including the Docstring or call signature of a function
or method. There are many functions available in the library.
Details are available on the docs.python.org website.

97
In [3]: from inspect import signature
In [4]: print(str(signature(load_workbook)))
(filename, read_only=False, keep_vba=False, data_only=False, keep_links=True)

The type() Function


In the Chapter 3 topic, “What is the Data Type? ,” we
used the type() function to examine the type of an object.
Chapter 6 also includes numerous examples using the type()
function.
print( type( my_var ) )

The id() Function


When dealing with immutable objects or scope issues, the
id() function is useful in isolating which object you are
referencing. Scope has to do with global vs. local variables.
print( id (bfr))
bfr = bfr + 1
print( id (bfr))

The repr() Function


The repr() function returns a string representation of an
object, and is useful in finding “whitespace.”

The len() Function


The len() function shows the length of the string or the
number of items in a data structure. For example,
len(mydictionary) would return the number of Dictionary key
pairs. len(mylist) would return the number of items in the
List.

98
4.9 Logging
Logging is a simple way to capture debugging data. Use
logging when the output in the Console pane scrolls and is
lost because there is too much data. Logging is also useful
when you’re working out code logic, or have a live program
with user reports of erratic behavior.
This script has a logging level set to ERROR, which means
it logs errors and critical events. For a thorough look at
logging, please refer to the docs.python.org .
logging.basicConfig(format=’%(asctime)s - %(message)s’,
datefmt=’%d-%b-%y %H:%M:%S’,
filename=’test.log’,
level=logging.ERROR)
When there is an exception on line 9 in the statement
10/my_int , the Python Interpreter logs a critical error to
the test.log file.
import logging
1
logging.basicConfig(format=’%(asctime)s - %(message)s’,
2
datefmt=’%d-%b-%y %H:%M:%S’,
3
filename=’test.log’,
4
level=logging.ERROR)
5
logging.error(‘The logging level is ERROR and above.’)
6
my_int = 0
7
try :
8
10 /my_int
9
except Exception:
10
logging.critical(“my_int is %s”, my_int,
11
exc_info=True)

The first time you run the program the logfile test.log is
created. The default mode is “append.” If the log file is not
created, try restarting Spyder. This is the output in the log
file.
29-Jan-19 10:29:33 - Logging level is ERROR and above.
29-Jan-19 10:29:33 - my_int value is 0
Traceback (most recent call last):
File “/Ch 4 code/Logging/logging.py”, line 13, in <module>
10/my_int
ZeroDivisionError: division by zero

99
To disable logging, use the “disable” method with the
appropriate argument, as shown below.
logging.disable(logging.CRITICAL)

To enable logging again, use the “disable” method with


the “NOTSET” argument.
logging.disable(logging.NOTSET)

4.10 The timeit() Function


The timeit() function can identify bottlenecks in your
code. Let’s say we want to time this block of code.

100
colors = (‘blue’, ‘red’, ‘green’)
for color in colors:
print(color)

Import the timeit module. Create a string “mycode ”


that encloses the code statements in triple quotes. In the
example below, the last line invokes the timeit method to
run the code 100 times.
from timeit import timeit
1
mycode = ‘’’
2
colors = (‘blue’, ‘red’, ‘green’)
3
for color in colors:
4
print(color)
5
‘’’
6
print(timeit(stmt=mycode, number=100
7
))

4.11 Focused Testing


Sometimes I need to focus on one part of my code, to the
exclusion of other areas. By providing test data for the steps
I’m excluding, I can focus on the defect. Let’s look at my
program that has five tasks.
1. Get KDP royalites.
2. Get the GBP exchange rate.
3. Calculate total sales for the month.
4. Calculate the average daily sales for the month.
5. Calculate the expected monthly sales.

Actual Result
When I run the code, the program halts. The Traceback
shows a ZeroDivisionError on line 65. I haven’t changed
anything in the program in several weeks. Until today the
program ran successfully. This is the code on line 65.
dailysales = (total/myday)

101
Incorrect Code
The value of “myday ” is set on line 64, as shown below.
As it happens, on the first day of the month, the statement
on line 64 evaluates to zero.
myday = (datetime.datetime.today().day-1 )
dailysales = (total/myday)
While this particular example is easy to troubleshoot,
when you have a program with external connections, it can
be a challenge to isolate the defect. With a slight
modification, I can use a variable “testmode ” as a switch to
use test values. When I want to test ‘datecalculations,’ I set
all the other conditional statements to use test data. In
effect, I remove all the other code from the equation and
only run lines 62-68.
For example, the “else” statement on line 54 sets gbp to
a value of 999.99 when testmode is “tst_datecalculations
.”

Figure 4.6 test_mode.py

4.12 Create Test Data


Use the smallest subset of data possible for testing. After
removing a chunk of data, ensure you still have enough data

102
for your program to function. If you’re debugging an error,
be careful to keep the data that recreates the error.
In this example, I changed the code on line 13 and
created an HTML data file. Rather than connecting to a live
website, I copied the “HTML” data to a file. I also removed
unnecessary headings and tables from the HTML file.

Figure 4.7 Test Data.py File


Below is a small excerpt of the html data, with the data I
need for my program.

Figure 4.8 Test HTML Data File

103
5. Exceptions

In this chapter we discuss


Kinds of Errors
The Stack Trace or Traceback Message
Try and Except
Raise
Assert
Built-in Error Types

To begin our discussion of exceptions, we’ll look at the


basic kinds of programming errors. When I say “kind” of
error, this is just a general classification to characterize
programming errors. When an event happens that the Python
Interpreter can’t process successfully, it stops the program
with an exception.
After an unhandled exception occurs, the Python
Interpreter displays the stack trace in a “Traceback ”
message is the Console pane with details about the
exception. In the topic, “Traceback Message,” you’ll see there
is a wealth of information in a Traceback message. Often the
Traceback message immediately points to the cause of the
error.
To handle exceptions, you can add “try and except ”
statements to deal with exceptions gracefully. For critical

104
events, we’ll look at the “raise ” command where you raise
your exception. When an object must be a certain value,
adding an “assert ” statement to trigger an exception is a
great time saver.
Finally, we’ll briefly look at the Python built-in exceptions
you’re likely to encounter when programming in Python.

5.1 Kinds of Errors


Generally, when things go wrong in a program, they fall
into one of three categories.

• Syntax Errors
• Logic or Semantic Errors
• Runtime Errors
Syntax Errors are usually obvious, and the Spyder Editor
points out Syntax errors with a yellow triangle. Runtime
errors occur when the Python Interpreter halts and displays
an exception. I find my “Logic” errors the most difficult to
identify because the program does what I told it to, but my
initial design or logic is flawed.

Syntax
A syntax error is raised by the parser when the parser
encounters a syntax error. The Spyder Editor makes it
virtually impossible to have Syntax errors. A yellow triangle
appears to the left of the line number if there is a Syntax
error in the code.
Chapter 7 demonstrates syntax errors in Example 5, and
Examples 7-12.

105
Logic or Semantic
With a logic error, the flaw is with me. I told the program
to do something, but it’s not the outcome I want. To identify
logic errors, I find it helpful to go back to the drawing board
and look at my initial “Intended Outcome” or pseudocode.
Pseudocode is an outline of your program design in simple
terms, often written in plain English.

Runtime
The challenge with debugging runtime errors is a line (or
suite) of code runs as expected several times, and then
suddenly halts with an error. As a program runs, variable
values change. Another example of a RunTime error is when
a program takes too long to run.
While general RunTime errors are flagged as a
“RunTimeError” by the Python Interpreter, what I am
referring to as “Runtime” is the overall kind of error. The
actual Traceback message displayed in the Console may
vary, as shown in Chapter 7 in Examples 5 and Examples 7-
12.
To research a runtime error, we need to look at the
values at the moment the error occurred When looking at
values, you may have a critical variable that must be a
certain value for your code to function. Assert statements
halt the program and warn you when values are outside the
parameters you require.
Another example of a Runtime error is a chunk of code
that takes too long to run. In this case, the function “timeit”
times program execution.

• Debug Mode
• Variable Explorer

106
• Interactive Mode
• Print Statements
Chapter 7 looks at these kinds of errors in Examples 1, 4,
6, 14, 15, and 17.

5.2 The Stack Trace or


Traceback
The Traceback includes this basic information.

• File
• Line Number
• Module
• Exception
• Exception Description
The next lines are a sample Console Traceback. I
abbreviated the file path for readability.

107
File “workbook.py”, line 289, in __getitem__
raise KeyError(“Worksheet {0} does not exist.”.format(key))
KeyError: ‘Worksheet Sheet1 does not exist.’

The Traceback details are as follows:


File: “workbook.py”
Line Number: 289
Module: __getitem__
Exception: KeyError
Exception Description: Worksheet Sheet1 does not exist.
This Traceback information provides the clues needed to
research many issues. In Chapters 6 and Chapter 7, I’ll often
refer back to the Exception in the Traceback.
Chapter 7, Examples 1, 2, 3, and 6 demonstrate
traceback screens.

Don’t Be Fooled
A misleading Traceback message “NameError” could be
hiding the Traceback message you want to see. In the
Chapter 4 topic, “Variables and Objects in Memory, ” we
looked at how the Python Interpreter creates variables and
objects when you run a program or script. In this example,
there is a variable “myint” of type “int.”
myint = 57
print(myint.upper)
If the program ran and created “myint” already, the
Console Traceback message is “AttributeError” because
there is no attribute “upper” for a variable “myint.” If the
program hasn’t run and created the variable “myint,” the
Console Traceback message is “NameError.”
When the program encounters an Out of Memory error,
the Traceback exception is rarely the actual cause of the
defect.

108
5.3 Try and Except
Unhandled exceptions halt the program and display a
Traceback with an exception error. When you add “try” and
“except” statements to your code, you can control how
exceptions are handled, and prevent your program from
unexpectedly halting. In this next example with “except,” you
can see where I added custom messages.

109
try :
gbpex = float(tables2[3 ].string[:6 ])
gbp = gbp/gbpex
print(“gbp converted to USD is:”, gbp)
except TypeError:
print(“Type error when converting exchange rate”)
except ZeroDivisionError:
print(‘ZeroDivisionError where gbpex is:’, gbpex)
except Exception as exceptdetails:
print(exceptdetails, ‘gbpex is:’, gbpex)
finally :
print(“Done calculating the gbp exchange rate.”)

The finally clause at the end runs whether the try clause
has an exception or not.

5.4 Raise
At any point, you can add your own “raise” statements in
your program to raise an exception, as shown below.
raise Exception(“I broke my program.”)

5.5 Assert
When your program depends on a statement to be true,
consider adding an “assert” statement to alert you if the
statement does not evaluate to “true.” When I was
calculating KDP royalties earlier, I found the GBP exchange
rate on a web site. In order for my program to calculate GBP
royalties in USD currency, “gbpex ” must be greater than
zero.
assert gbpex > 0 , ‘gbpex must be > ‘ + str(gbpex)
Now when my program runs and “gbpex ” is not greater
than zero, an exception is raised. The Console displays a
Traceback message, as shown below.

110
AssertionError: gbpex must be > 0

5.6 Built-in Error Types


The following list of built-in exceptions is a reference for
the examples that follow. For a complete list of exceptions,
visit https://docs.python.org/3/library/exceptions.html .

ArithmeticError
ArithmeticError is the base class for built-in exceptions for
various arithmetic errors.

AssertionError
An AssertionError is raised when the assert statement
fails.

AttributeError
The AttributeError is raised on attribute assignment or
when the reference fails. When an object does not support
attribute references or attribute assignments at all, a
TypeError is raised. For example, an “int” object has no
attribute “upper.” The code below would cause an
AttributeError :
myint = 57
print(myint.upper)
Because a “string” object does have an attribute “upper,”
this code for a string is valid.
mystr = ‘age’
print(mystr.upper())

111
To view attributes of an object named “mystr ” run the
program, then type “dir(mystr) ” in the Python Console .
You must run the program for the Python Interpreter to
create the variable “mystr.” If you haven’t run the
program , the Python Interpreter displays a NameError
exception. See Chapter 7, Example 6, for a description of
debugging an AttributeError .
In Chapter 7, Example 6 demonstrates an AttributeError.

In Python, Objects have attributes. So, for example, the


object “ws1 ” has an attribute named “.cell .” In this
example, the dotted notation would be ws1.cell() .

EOFError
Raised when the input() function hits the end-of-file
condition without reading any data. In Chapter 7, Example
15 demonstrates an EOFError.

FloatingPointError
Raised when a floating-point operation fails.

ImportError
When Python Interpreter has trouble loading a module,
the Interpreter raises an ImportError.

Indentation Error
The IndentationError is raised when there is an incorrect

112
indentation. In Chapter 7, Example 5 demonstrates an
IndentationError.

IndexError
An IndexError is raised when the index of a sequence is
out of range. If the index is not an integer, TypeError is
raised. The base class of an IndexError is a LookupError. See
Examples 1-2 in Chapter 7.

IOError
Starting from Python 3.3, an IOError is an OSError.

KeyError
A KeyError is raised when a key is not found in a
dictionary and is a subclass of LookupError. See Example 20.

KeyboardInterrupt
A KeyboardInterrupt is raised when the user hits the
interrupt key (Ctrl+c or delete).

LookupError
A LookupError is the base class for KeyError and
IndexError.

MemoryError
113
Raised when an operation runs out of memory.

ModuleNotFoundError
The ModuleNotFound error indicates a module could not
be located and is a subclass of ImportError.

NameError
Raised when a variable is not found in the local or global
scope. This exception occurs when an identifier is invalid or
an unknown name. For example, a misspelled identifier can
cause a NameError. The Spyder IDE would highlight a
NameError. In Chapter 7, Examples 3, 10, 13, and 22
demonstrate NameErrors.

The Chapter 4 topic, “Variables and Objects in Memory,”


outlined how the Python Interpreter creates variables
and objects when you run a program or script. If you
type your object name in the Console and the Traceback
says “NameError,” ensure that you ran the line of code
that creates the object.

OSError
Raised when a system operation causes a system-related
error, such as failing to find a local file on disk.

OverflowError
Raised when the result of an arithmetic operation is too

114
large to be represented. The OverflowError is a subclass of
ArithmeticError.

RecursionError
A RecursionError is derived from the base class
RuntimeError. A RecursionError is raised when the maximum
recursion depth is exceeded.

RuntimeError
Raised when an error is detected that does not fall under
any other category.

StopIteration
Raised by the next() function to indicate that there is no
further item to be returned by the iterator.

SyntaxError
Raised by the parser when a syntax error is encountered.
The Spyder Editor makes it virtually impossible to have
Syntax errors. A yellow triangle appears to the left of the line
number if there is a Syntax error in the code.

TabError
Raised when indentation contains an inconsistent use of
tabs and spaces. The TabError is a subclass of
IndentationError.

115
SystemError
Raised when the interpreter detects an internal error.

SystemExit
Raised by the sys.exit() function.

TypeError
Raised when a function or operation is applied to an
object of an incorrect type. Attempting to perform an
operation on an incorrect object type.

ValueError
A ValueError is raised when a function gets an argument
of correct type but improper value. For example, a datetime
object considers a time value for seconds < 60 or a month
between 1 and 12 to be valid. A datetime month value of 13
creates an exception, and the Python Interpreter displays a
ValueError. The syntax below is invalid for a datetime object:
d1 = datetime( 1999, 13, 31)

In Chapter 7, Examples 21, 23, and 31 demonstrate a


ValueError.

ZeroDivisionError
Raised when the second argument of a division or modulo
operation is zero. The ZeroDivisionError is a subclass of
ArithmeticError.

116
6. Try This

In this chapter we discuss


What is the Object Value?
String and Number Variable Values
Tuple Objects and Values
List Objects and Values
Dictionary Objects and Values
Does the Object Have a Value of None?
What is the Object Type?
What is the Length of the Object?
What are the Function/Method Arguments?
What is the Return Object of the Function?

The examples in the next chapter do have several


suggestions on how to identify a particular bug and are great
if you’re experiencing the same problem. But this is the real
world, and we both know that’s not likely to happen. My
concern with only using “Examples,” is you’ll rarely encounter
the same issue when working with your code. Your situation
is unique, and may not fit one of the examples.

117
To provide the missing piece of the debugging puzzle, I’m
going to take some time in this Chapter to break down the
debugging process into a reusable format. I’ll cover some
common issues. Unfortunately, my issue list isn’t going to be
all-inclusive, but I hope it kickstarts your debugging
experience.
While an odd chapter title, “Try This,” is a fitting name.
When I was learning to program, I would share my dilemmas
with a good friend. He would say, “Try this...” and offer a few
suggestions. That little nudge in the right direction was a
godsend that helped me find my way. I’m not sure if I can
create that experience for you, but I’m going to try.
As we work through the next sections, you’ll notice a
common theme, where we look at these topics in different
contexts.
• Object Values
• Types of Objects
• Length of Objects
• Passing Arguments to Functions or Methods.
• The Return Object of a Function
We’ll look at the common objects outlined below. This list
of objects isn’t every possible Python object, but I think
these are enough to get you started.
• Strings and Numbers
• Tuples
• Lists
• Dictionaries

118
It can be exasperating when you have a runtime or logic
error and have no idea where to start debugging. The
suggestions in this chapter may help you get started
debugging your program.

6.1 What is the Object


Value?
When I am debugging, often, the first thing I check is the
object value. If you decide to take the hands-on approach
and add print statements to your code or use Interactive
Mode in the Console, the next few topics show you examples
for strings, tuples, lists, and dictionaries. In the case of data
structures like lists, tuples, and dictionaries, I’ll also include
the syntax to inspect all items or a single item. This content
may be a bit repetitive, but on the plus side, this is a handy
reference.

6.2 String and Number


Variable Values
In this topic, I’ll look at several ways to find the value of
String and Number Variables.

Print the Value of a String Variable


Add a print statement to your script in the Editor
window, and run your program.
mystring = “Purple Peanuts”
In the example the follows, I add a print statement in the

119
Editor window. When I run the program, the output of the
print statement is shown in the Console pane. The Console
is the Python Shell.
A String Identifier: mystring
Value: purple peanuts
Reference: Chapter 4 - Add Print Statements
1
mystring = “purple peanuts”
2
print(mystring)
3

In [1 ]: runfile(‘C:/SampleScript.py’, wdir=’C:’)
purple peanuts

Inspect a Number Variable in Debug


Mode
Debug Mode with Variable Explorer is a simple way to see
object values as you step through your code. In this
example, the Editor has one line to create a string variable
named “mynumber.”
mynumber = 57

1. First, I run the program in Debug Mode.


2. Next, I type ” mynumber ” in the Console . Because I
am in Debug Mode, the Console prompt is ipdb> .
The Variable Explorer also shows the value of the “
mynumber” variable.

Inspect a String Value with


Interactive Mode
To see the value of the string in Interactive Mode, type
the string name “mystring” in the Console .

120
mystring = “purple peanuts”
A String Identifier: mystring
Value: purple peanuts
Reference: Chapter 4 - Interactive Mode

1. Run the program to create the variables in memory.


2. Type “mystring” in the Console.
3. The Python Interpreter displays the value of “mystring”
on the next line in the Console .
In [2 ]: mystring
Out[2 ]: ‘purple peanuts’

6.3 Tuple Objects and


Values
In this topic, I’ll look at several ways to inspect Tuple
Objects and Tuple Item values. To create a Tuple, use this
syntax in the Editor :
mytuple = (‘Apple’, ‘Orange’, ‘Watermelon’)

Print All Tuple Item Values


Add a print statement to your script in the Editor window
and run your program. The output of the print statement is
shown in the Console pane.
All Items in the Tuple
Identifier: mytuple
Value: Name: Apple, Orange, Watermelon
Reference: Chapter 4 - Add Print Statements
2
3 print(mytuple)
4

121
In [1 ]: runfile(‘C:/SampleScript.py’, wdir=’C:’)
(‘Apple’, ‘Orange’, ‘Watermelon’)

Print a Tuple Item Value


To see the value of a Tuple item, type “mytuple[0] in the
Console. The first item in the Tuple has an index value of 0 .
A Tuple Item
Identifier: mytuple[0 ]
Value: Name: Apple
Reference: Chapter 4 - Add Print Statements

1. Add a print statement to your script in the Editor window.


2. Run your program. The output of the print statement is
shown in the Console pane.
1
2 print(mytuple[0 ])
3

In [1 ]: runfile(‘C:/SampleScript.py’, wdir=’C:’)
Apple

Inspect All Tuple Items in Interactive


Mode
To see all the values of a tuple named “mytuple,” type
“mytuple” in the Console .
All Items of the Tuple
Identifier: mytuple
Value: Name: Apple, Orange, Watermelon
Refe rence: Chapter 4 - Interactive Mode

1. Run the program to create the variables in memory.


2. Type “mytuple” in the Console in Interactive Mode . The
Python Interpreter displays the value of “mytuple” on the

122
next line in the Console .
Object Type Identifier Value

A Tuple mytuple purple peanuts

In [2 ]: mytuple
Out[2 ]: (‘Apple’, ‘Orange’, ‘Watermelon’)

Inspect A Tuple Item in Interactive


Mode
To see the value of a tuple item “mytuple,” type
“mytuple” in the Console . The first item in the Ruple has an
index value of 0 .
A Tuple Item
Identifier: mytuple[0 ]
Value: Name: Apple
Refer ence: Chapter 4 - Interactive Mode

1. Run the program to create the variables in memory.


2. Type “mytuple[0]” in the Console in Interactive Mode .
The Python Interpreter displays the value of the
“mytuple[ 0 ]” object on the next line in the Console .
In [2 ]: mytuple[0 ]
Out[2 ]: ‘Apple’

6.4 List Objects and Values


In this topic, I’ll look at several ways to inspect List
Objects and List Item values. To create a List, use this
syntax:
mylist = [‘Soda’ , ‘Water ’ , ‘ Coffee’]

123
Print All List Item Values
In this example, I print out all List item values to the
Console pane.
All Items of the List
Identifier: mylist
Value: Name: Soda, Water, Coffee
Reference: Chapter 4 - Add Print Statements

1. Add a print statement to your script in the Editor window.

2. Run your program. The output of the print statement is


shown in the Console pane.
1
2 mylist = [‘soda’, ‘water’, ‘coffee’]print(mylist)
3

In [1 ]: runfile(‘C:/SampleScript.py’, dir=’C:’)
(‘Soda’, ‘Water’, ‘Coffee’)

Print the Value of a List Item


To print the value of a List item, add a print statement to
your script in the Editor window, and run your program. The
second item in the List has an index value of 1 .
A List Item
Identifier: mylist[1 ]
Value: Soda, Water, Coffee
Reference: Chapter 4 - Add Print Statements

1. Add a print statement to your script in the Editor window.


2. Run your program. The output of the print statement is
shown in the Console pane. In the example below, the
output is “Water.”
1
2 mylist = [‘soda’, ‘water’, ‘coffee’] print(mylist[1 ])
3

124
In [1 ]: runfile(‘C:/SampleScript.py’, wdir=’C:’)
soda

Inspect a List Item in Debug Mode


Debug Mode with Variable Explorer is a simple way to
see object values as you step through your code. In this
example, I run the program in Debug Mode . Because I am
in Debug Mode, the prompt is ipdb> .
Notice the Variable Explorer shows the values in the
“drinks” list. The third item is “coffee” and has an index
value of 2 .
A List Item
Identifier: drinks[2 ]
Value: coffee
Reference: Chapter 4 - Debug Mode

1. Run the program in Debug Mode.


2. Type ” drinks[ 2 ] in the Console .

Figure
6.1

Inspect All Items of a List in the


Console
To see all values of a List, type the list name in the
Console .

125
All Items in the List
Identifier: mylist
Value: Name: Soda, Water, Coffee
Reference: Chapter 4 - Interactive Mode

1. Run the program.


2. Type “mylist” in the Console. The Python Interpreter
displays the value of “mylist” on the next line in the
Console .
In [2 ]: mylist
Out[2 ]: [‘Soda’, ‘Water’, ‘Coffee’]

Inspect a List Item in the Console


In this example, I run the program and type “mylist[1]”
in the Console. The second item in the List has an index
value of 1 .
A List Item
Identifier: mylist[1 ]
Value: Name: Water
Reference: Chapter 4 - Interactive Mode

1. Run the program.

2. Type “mylist[ 1 ]” in the Console . The Python Interpreter


displays the value of mylist[ 1 ] in the Console .
In [2 ]: mylist[1 ]
Out[2 ]: Water

6.5 Dictionary Objects and


Values
In this topic, I’ll look at several ways to inspect Dictionary

126
Objects and Dictionary Key-Pair values. To create a
Dictionary, use this syntax:

mydictionary = { ‘Name’ : ‘Zimmerman’ ,


‘Grade’ : ‘A’ ,
‘Course’ : ‘Python Programming’ }

Print the Value of a Dictionary Key-


Pair
To print the value of a Dictionary item, add a print
statement to your script in the Editor window, and run your
program.
A Dictionary Key-Pair
Identifier: mylist[1 ]
Value: Soda, Water, Coffee
Reference: Chapter 4 - Add Print Statements

1. Add a print statement to your script in the Editor window.


2. Run your program. The output of the print statement is
shown in the Console pane. In the example below, the
output is “Water.”

1 mydictionary = { ‘Name’ :
2 ‘Zimmerman’ ,
3 ‘Grade’ : ‘A’ ,
4 ‘Course’ : ‘Python Programming’
5 }
print(dictionary[‘Name’])
In [1 ]: runfile(‘C:/SampleScript.py’, wdir=’C:’)
Water

Inspect All Dictionary Items in the


Console
127
To see all the key-pairs of a Dictionary named
“mydictionary,” type “mydictionary” in the Console . In this
example, I run the program, and the Python Interpreter
displays the value of “mydictionary” on the next line in the
Console .
All Dictionary Items
Identifier: mydictionary
Key-Pair Values: Name: Zimmerman, Grade: A
Reference: Chapter 4 - Interactive Mode

1. Run the program.


2. Type “mydictionary” in the Console. The Python
Interpreter displays the value of “mylist” on the next line
in the Console .
In [2 ]: mydictionary
Out[2 ]: ‘Name’: ‘Zimmerman’, ‘Grade’: ‘A’

Inspect a Dictionary Item Value in


the Console
Once you know a key name in a Dictionary, you can find
the value of the Dictionary key-pair item. In this example, I
run the program and type mydictionary[‘grade’] in the
Console. The key name is “grade.”
A Dictionary Item
Identifier: mydictionary[‘Grade’]
Value: A
Reference: Chapter 4 - Interactive Mode

1. Run the program.


2. Type “mydictionary[‘grade’]” in the Console . The Python
Interpreter displays the value of “mydictionary[‘Grade’]”
on the next line in the Console .

128
In [2 ]: mydictionary[‘Grade’]
Out[2 ]: ‘A’

Inspect a Dictionary Item in Variable


Explorer
Debug Mode with Variable Explorer is a simple way to see
object values as you step through your code. In this
example, I create a variable “schoolinfo” in a “for statement”
on line 5. When I step through the “for loop” twice in Debug
Mode, the “schoolinfo” variable has the value of the second
key-par in “mydictionary.”
A Dictionary Item
Identifier: mydictionary[‘Grade’]
Variable: schoolinfo
Value: A
Reference: Chapter 4 - Debug Mode Variable Explorer

Figure 6.2 Variable Explorer


When you double click on the name of a Dictionary in
Variable Explorer, a pop-up window opens

Figure 6.3 Pop-up in Variable Explorer

6.6 Does the Object have a

129
Value of None or
Whitespace?
When importing external data into Python data
structures, it is not uncommon to have items with a value of
“None” or unexpected whitespace. For example, if you import
an Excel worksheet with empty cells, those List items have a
value of “None.” Also, sometimes strings are null or equal to
“”.
Functions with return values can also sometimes return
“None.” The value “None” is returned when you don’t have a
return value for all paths in the function, as explained in the
Chapter 3 topic, “Function Return Values .” Example 17 in
Chapter 7 also illustrates a function that returns “None.”
The “None” value causes problems when working with
functions that expect a particular type or value for an object.
For example, the DateTime library function “.strftime”
expects an object of type “datetime”, “time”, or “date.” If the
object has a value of “None,” the Python interpreter displays
an error, as shown in Chapter 7, Example 20 .
Sadly, this is also one way Divide by Zero errors happen
in a program. When you convert an item in a data structure
from a string to an “int,” an item with a value of “None”
becomes a zero. The Divide by Zero error is shown in the
Examples Chapter, Example 24 and 17 , and includes a
sample “if statement” to test for a “None” value.

Whitepsace
Another cause of unexpected consequences is
whitespace. There may be a tab, line return, or some other
character that impacts a search or comparison. These

130
functions are useful for removing those unseen characters.
lstrip() Remove left whitepspace characters.
rstrip() Remove right whitespace characters.
strip() Remove whitespace characters from both sides.

6.7 What is the Object


Type?
In Debug Mode, the Variable Explorer shows the type of
the Object. Another option is to add a print statement or type
in the Console, as outlined earlier.
print(type(mystring))
print(type(myfunction())
Object Syntax
type(mystring)
type(mytuple)
number, string or data structure
type(mylist)
type(mydictionary)
a Tuple item type(mytuple[0])
a List item type(mylist[0])
a Dictionary item type(mydictionary(‘Name’]

6.8 What is the Length of


the Object?
The Len() function shows the length of the string or the
number of items in a data structure. For example,
len(mydictionary) would return the number of Dictionary key
pairs. len(mylist) would return the number of items in the
List.
Object Syntax
len(mystring)

131
number, string or data structure len(mytuple)
len(mylist)
len(mydictionary)
a Tuple item len(mytuple[0])
a List item len(mylist[0])
a Dictionary item len(mydictionary(‘Name’]

6.9 What are the Function


Arguments?
First, identify what type of arguments a Function expects.
Then, check your arguments to be sure they are the correct
type and value, as outlined previously. The Help pane and
searching the Internet are a great way to review the
definition of the function to ensure both the arguments and
return objects are what you expect. In the Console, you can
also use these introspection functions for more information
about your object, as outlined in Chapter 4 in the topic
“Interactive Mode .”
In [1 ]: myfunction?
In [2 ]: dir(myfunction)
In [3 ]: help(myfunction)
The reference for built-in functions can be found on
docs.python.org . Example 26 in Chapter 7 looks at these
options.

The Function Call Signature


For additional information on the “openpyxl ” method
“load_workbook ,” I can look at the “calThe Console is tl
signature” for a callable object. In Python v3.x, PEP 362
specifies the function signature object and lists each
parameter accepted by a function. In the Console , import
the module and print the signature for the object, as shown

132
below. Chapter 7, Example 20, also illustrates this syntax
from PEP 362 . The inspect library can also display the
DocString mentioned in the topic “Classes” in Chapter 3 .

133
In [3]: from inspect import signature
In [4]: print(str(signature(load_workbook)))
(filename, read_only=False, keep_vba=False, data_only=False, keep_links=True)

6.10 What is the Return


Object of the Function?
The Interactive Mode of the Console is a great way to
check what a function returns. You may want to check the
value, type, or length.
print(myfunction())
type(myfunction())
len(myfunction())
The Help pane is another way to review the definition of
the function, to ensure both the arguments and return object
is what you expect. A function returns one object, but that
object might be a tuple with several items. Example 26 in
Chapter 7 looks at these options.

134
7. Examples

In this Chapter, we take “debugging” for a spin. These


examples build on everything we’ve looked at so far. It
doesn’t matter if you landed here first, or read everything to
this point. Either way, I provide references to those previous
topics, in case you want to take a brief sojourn to review
them.
Ex Description Built-in Error Type Kind
1 List index out of range IndexError Runtime
List index out of range (Example 1
2 IndexError Runtime
continued)
3 Wrong Variable Name NameError Logic
4 Invalid Assignment Runtime Runtime
5 While statement not indented IndentationError Syntax
6 Method arguments incorrect AttributeError Runtime
7 Empty Block is illegal IndentationError Syntax
8 Parentheses not matched SyntaxError Syntax
9 Colon misssing SyntaxError Syntax
10Case sensitive NameError Runtime
11Keyword missing SyntaxError Syntax
12Illegal characters or keyword SyntaxError Syntax
13Misspelled identifier NameError Runtime
14File doesn’t exist FileNotFoundError Runtime
15Adding incorrect types TypeError Runtime
16Misspelled keyword SyntaxError Syntax
17Value is none TypeError Runtime
18Module not found AttributeError Runtime
19Module not found ModuleNotFoundErrorRuntime
20Key not in Dictionary KeyError Runtime
21Arugment is incorrect type ValueError Runtime
22Object not found- NameError NameError Runtime
23Invalid data passed to method ValueError Runtime

135
25 There is a mistake in a math calculation Logic Error
26 Assigning datetime value causes ValueError ValueError Runtime

For each example that follows, I use a systematic approach to


examine the program.
Intended Outcome : What I want the program to do is
the Intended Outcome.
Actual Result : What the program did is the Actual
Result.
Incorrect Code : The Incorrect Code is the actual code
that is not working properly.
Debugging Experiment : The steps I use to “debug”
what the program is actually doing comprise the Debugging
Experiment.
How to Resolve the Issue : This section is a brief
description of the change to the code to resolve the issue.
Correct Code : The Correct Code works as I intended.
References : The References list previous topics related
to this example.

Ex 7.1 List Index Out of


Range
Description: The list index is out of range.

Intended Outcome
There are two Lists in this program, “meals” and “fruits.”
I want the program to loop through each list and print the
items in order.

136
Actual Result
The Console output shows the print statement on line 6
repeats with the first item in the List.

137
Incorrect Code
This is the Example 1 Code before any changes. Can you
spot the three areas we need to fix? We’ll look at each error
in Examples 1-3.
meals = [‘breakfast’, ‘lunch’, ‘snack’, ‘dinner’]
fruits = [‘apple’, ‘orange’, ‘grape’]
i=0
while i < 4 :
j=0
print(“my meal is: “, meals[i])
while j < 4 :
print(“My choice of fruit is: “, fruits[i])
j=j+1
i=i+1

Debugging Experiment
In this example, when I run the program, it loops
continuously. Next, I use Debug Mode to research what is
happening.

1. Run the program. The program runs endlessly. The


program is in an infinite loop. In the Console , the Python
Interpreter repeatedly outputs the print statement from
line 6.
2. To stop the program, in the Consoles menu, I select
“Restart kernel.”
Double click twice on line 6 to add a breakpoint. Select
“Debug File” on the menu, as shown below.

138
3. The Console prompt changes to ipdb> to indicate you are
in Debug Mode. In the Console , type “ s ” to step
through the program. The Python Interpreter moves to
the next line.
Type “ s ” a few times, and you’ll notice the program loops
back to line 4. Variable Explorer shows the value of “ i ” is
0 and is not changing as the program runs.
4. In the earlier figure, the print statement on line 6 was
repeatedly output to the Console , indicating that the
“while loop” on line 4 is looping continuously. I suspect
that my counter “i” is not incremented properly on line
10.
In the Console, pane, type “ q ” to quit Debug Mode . The
next topic outlines the change to resolve this issue.

How to Resolve the Issue


In the Editor , I indent line 10. Now line 10 is part of the
while loop that begins on line 4. One error is fixed, but there
is another error we’ll look at in Example 2.

139
Good Code
meals = [‘breakfast’, ‘lunch’, ‘snack’, ‘dinner’]
fruits = [‘apple’, ‘orange’, ‘grape’]
i=0
while i < 4 :
j=0
print(“my meal is: “, meals[i])
while j < 4 :
print(“My choice of fruit is: “, fruits[i])
j=j+1
i=i+1

Reference
These topics from previous chapters are a good reference
for this example.
Chapter 4 - Add Print Statements
Chapter 4 - Interactive Mode
Chapter 4 - Debug Mode Variable Explorer
Chapter 4 - Infinite Loop
Chapter 5 - Traceback
Chapter 5 - IndentationError
Chapter 5 - IndexError
Chapter 6 - Check Object Type

Ex 7.2 Index Error


Description: The list index out of range. This kind of
runtime error appears when you run the program.

Intended Outcome

140
There are two Lists in this program, “meals” and “fruits.”
I want the program to loop through each list and print the
items.

Actual Result
The print statement on line 8 fruits[i] causes an
IndexError.

Incorrect Code
Example 2 code before any changes follows.
1 meals = [‘breakfast’ , ‘lunch’ , ‘snack’ , ‘dinner’ ]
2 fruits = [‘apple’ , ‘orange’ , ‘grape’ ]
3 i=0
4 while i < 4 :
5 j=0
6 print(“my meal is: “, meals[i])
7 while j < 4 :
8 print(“My choice of fruit is: “, fruits[i])
9 j=j+1
10 i=i+1

Debugging Steps
In this Example the program halts. I use Debug Mode to
research what is happening.

1. Run the program. The Python Interpreter halts because of


an exception and displays an IndexError in the Console
In the Console , the Python Interpreter displays a Traceback
message telling me the error is in Line 8. If I click on “line
8” in the Console , it is a hyperlink to that location in my
code in the Editor pane.

141
2. Type %debug In the Console, pane to start Debug Mode.
The Console prompt changes to ipdb> .
3. Type fruits[3] In the Console, pane. The Variable Explorer
shows j has a value of 3, so fruits[i] evaluates to
fruits[3]. The message “IndexError: list index out of
range” is displayed.

4. Now type fruits[2] In the Console, pane. The value ‘grape’


is displayed. Grape is the last item in the “fruits” list. The
range of the fruits list is 0 to 2.
If this had been a long list, I could have typed len(fruits) In
the Console , to see how many items were in the list.
In the Console, pane, type “ q ” to quit Debug Mode. The
next topic outlines the change to resolve this issue.

How to Resolve the Issue


In the Editor , I update line 7.
while j < 3:

142
Figure 7.1 Corrected Code

143
Good Code
1 meals = [‘breakfast’ , ‘lunch’ , ‘snack’ , ‘dinner’ ]
2 fruits = [‘apple’ , ‘orange’ , ‘grape’ ]
3 i=0
4 while i < 4 :
5 j=0
6 print(“my meal is: “, meals[i])
7 while j < 3:
8 print(“My choice of fruit is: “, fruits[j])
9 j=j+1
10 i=i+1

Reference
These topics from previous chapters are a good reference
for this example.
Chapter 4 - Debug Mode
Chapter 4 - Interactive Mode
Chapter 4 - Debug Mode Variable Explorer
Chapter 5 - Traceback
Chapter 5 - IndexError
Chapter 6 - Check Object Type
Chapter 6 - Check Length of Object

Ex 7.3 Wrong Variable


Description: The code references the wrong variable
name.
In this example, there is a flaw in the overall design or
logic of my program. The program does what I coded, but
the outcome is not what I intended. In the Console, my print
statement does not iterate through my list of fruits.

144
Intended Outcome
The program should print a list of fruits for each meal.

Actual Result
The program halts with an IndexError exception.

145
Incorrect Code
Example 3 code before any changes follows.
meals = [‘breakfast’, ‘lunch’, ‘snack’, ‘dinner’]
fruits = [‘apple’, ‘orange’, ‘grape’]
i=0
while i < 4 :
j=0
print(“my meal is: “, meals[i])
while j < 3:
print(“My choice of fruit is: “, fruits[i])
print(“j is: “, j)
j=j+1
i=i+1

Debugging Steps
1. When I run the program, the Python Interpreter halts
with an error. The Traceback shows the IndexError was
caused by line 8.

2. In the Console , I type fruits[i] , which returns the same


IndexError.
Variable Explorer shows “ i ” has a value of 3. The fruits list
has three items, and the indices are 0-2. Now I realize I
should have used the “ j ” variable as a counter for the
fruits list.

146
At this point, I just typed a statement in the Console , so I
don’t need to exit Debug Mode . Instead, I’ll update my
script in the Editor pane to resolve the issue.

How to Resolve the Issue


In the print statement I change the variable to “j.”
print (“My choice of fruit is:” , fruits[j])

147
Good Code
meals = [‘breakfast’, ‘lunch’, ‘snack’, ‘dinner’]
fruits = [‘apple’, ‘orange’, ‘grape’]
i=0
while i < 4 :
j=0
print(“my meal is: “, meals[i])
while j < 3:
print(“My choice of fruit is: “, fruits[j])
print(“j is: “, j)
j=j+1
i=i+1

Reference
These topics from previous chapters are a good reference
for this example.
Chapter 3 - IndentationError
Chapter 4 - Debug Mode
Chapter 4 - Debug Mode Variable Explorer
Chapter 6 - Check Object Type

Ex 7.4 Invalid Assignment


Description: The assignment statement is invalid. This
kind of runtime error is uncovered when you run the
program.

Intended Outcome
Print “mylist” items to the Console.

148
Actual Result
The Console output shows the print statement on line 4
repeats with the first item in the List.

149
Incorrect Code
This is the Example 4 code before any changes.
mylist = [‘soda’, ‘water’, ‘coffee’]
i=0
while i < 3:
print(mylist[i])
i =+ 1

Debugging Steps
1. Run the program. The program runs endlessly. The
program is caught in an an infinite loop. In the Console ,
the Python Interpreter repeatedly outputs the print
statement from line 4.
2. To stop the program, in the Consoles menu, I select
“Restart kernel.”
Double click twice on line 4 to add a breakpoint. Select
“Debug File” on the menu, as shown below.
3. The Console prompt changes to ipdb> to indicate you are
in Debug Mode. In the Console , type “ s ” to step
through the program. The Python Interpreter moves to
the next line.
Type “ s ” a few times, and you’ll notice the program loops
back to line 3. Variable Explorer shows the value of “ i ” is
0 and is not changing as the program runs.

How to Resolve the Issue


The counter is not incremented on line 5 because I
reversed the syntax. The statements “i = i + 1” and “i += 1”
both increment the “i” counter.

150
Good Code
mylist = [‘soda’, ‘water’, ‘coffee’]
i=0
while i < 3:
print(mylist[i])
i += 1

Reference
These topics from previous chapters are a good reference
for this example.
Chapter 4 - Debug Mode
Chapter 4 - Debug Mode - Variable Explorer
Chapter 4 - Infinite Loop

Ex 7.5 While Indentation


Error
Description: The “while” statement is not indented
properly. The Console displays an IndentationError .

Intended Outcome
Print a list of numbers.

Actual Result
When I run the program, it halts with an
IndentationError.

151
Incorrect Code
This is the Example 5 code before any changes.
wadofcash = [111, 222, 333, 444 ]
i=0
x=3
while i <= x:
print(wadofcash[i])
i=i+1

Debugging Steps
Spyder displays a yellow warning triangle next to the
print statement on line 6. When I hover my mouse over the
triangle, a pop-up message is displayed, as shown below.
If I run the program, the Console displays an
IndentationError .

Figure 7.2 Indentation Warning

How to Resolve the Issue


Indent the print statement on line 6.

152
Good Code
wadofcash = [111, 222, 333, 444 ]
i=0
x=3
while i <= x:
print(wadofcash[i])
i=i+1

Reference
These topics from previous chapters are a good reference
for this example.
Chapter 4 -Help()
Chapter 5 - Traceback
Chapter 5 - IndentationError

Ex 7.6 Incorrect Method


Arguments
Description: The openpyxl “cell” method has incorrect
attributes. The Console displays an AttributeError .

Intended Outcome
My intention was for the code to open an Excel file and
print each column 2 value as the program iterates through
the rows.

Actual Result
153
The program halted with an “AttributeError” exception
when run with the Python 2.7 Interpreter. The program runs
fine on my Python 3 environment. This AttributeError
indicates the Python Interpreter doesn’t recognize the line 8
syntax.
Line 8 is calling a method in a class. In the discussion of
Classes in Chapter 3, we created an instance of a class. Valid
attribute names of a class include both “data attributes ”
and “methods .” Python objects have attributes that are
referenced with the dot notation.

154
Incorrect Code
This is the Example 6 code before any changes.
from openpyxl import load_workbook
wb1 = load_workbook(‘Before.xlsx’, data_only=True)
ws1 = wb1[“ExportedData”]
bfr = 2
while bfr <= ws1.max_row:
bfritem = ws1.cell(bfr, 2 ).value
print(bfritem)
bfr = bfr + 1

Debugging Experiment
In this example, when I run the program, the Python
Interpreter prints an “AttributeError” to the Console. I use
Help to research what is happening.

1. Run the program. The Python Interpreter halts because of


an exception and displays an AttrbuteError in the
Console .
In the Console , the Python Interpreter displays a Traceback
message telling me the error is in Line 8. If I click on “line
8” in the Console , it is a hyperlink to that location in my
code Ex_6_WRONG.py in the Editor pane.

2. The issue seems related to the object on line 8, and I


suspect there is something wrong with the syntax for the
object value. I’m curious about what syntax I should use
with the cell method. In the Console, type
help(ws1.cell()) or dir(ws1.cell()) for more information

155
on the object.

3. Help indicates the Python Interpreter could not use the


values for row and column when calling the function “ cell
.” In line 8, I need to add the argument keywords (or
names).
In the Console pane, type “ q ” to quit Debug Mode. The
next topic outlines the change to resolve this issue.

How to Resolve the Issue


In the Editor pane, update line 8 of Ex_6_WRONG.py to
use the keywords, as shown below. This change ensures the
program runs with Python 2.7 or 3.7.
bfritem = ws1.cell(row=bfr, column=2 ).value

156
Good Code
from openpyxl import load_workbook
bfritem = ws1.cell(row=bfr, column=2 ).value
wb1 = load_workbook(‘Before.xlsx’, data_only=True)
ws1 = wb1[“ExportedData”]
bfr = 2
while bfr <= ws1.max_row:
bfritem = ws1.cell(row=bfr, column=2 ).value
print(bfritem)
bfr = bfr + 1

Reference
These topics from previous chapters are a good reference
for this example.
Chapter 3 - Attributes
Chapter 3 - Methods
Chapter 4 - Help()
Chapter 4 - Interactive Mode
Chapter 5 - Traceback
Chapter 5 - AttributeError
Chapter 6 - Check Arguments

Ex 7.7 Empty Block of Code


Description : An empty block of code is illegal. The
Console displays an IndentationError .

Intended Outcome
While writing a program, I want to have a block of code
that does nothing. At some point, I intend to add logic.

157
Actual Result
The Python Interpreter has an IndentationError
exception.

Incorrect Code
This is the Example 7 code before any changes.
for mynum in [157, 19, 56 ]:
if mynum == 157 :
else:
print(‘Happy birthday, you are’, mynum)

Debugging Steps
The Console shows an IndentationError on line 3. As is
often the case, the actual error is the line above.

How to Resolve the Issue


In keeping with my design goal, I want the code to do
nothing, so I add a pass() statement.

158
Good Code
for mynum in [157, 19, 56 ]:
if mynum == 157 :
pass
else:
print(‘Happy birthday, you are’, mynum)

Reference
These topics from previous chapters are a good reference
for this example.
Chapter 4 - Help()
Chapter 5 - Traceback
Chapter 5 - RuntimeError
Chapter 5 - SyntaxError

Ex 7.8 Parentheses Not


Matched
Description: Parentheses not matched. The Console
displays a SyntaxError .

Intended Outcome
On line 3, I want to calculate projected sales.

Actual Result
When I run the program, the Console displays a
Syntaxerror in line 3.

159
Incorrect Code
This is the Example 8 code before any changes.
sales = 150.00
days = 31
projectedsales = (sales/days)*31 )

Debugging Steps
The Editor displays a red x to the right of line 3,
indicating the parser identified invalid syntax. When I hover
my mouse over the parentheses on that line, the paired
parentheses are highlighted in green.

When I move my mouse to the end of the line, the last


parenthesis is highlighted in orange, indicating there is no
corresponding parenthesis.

How to Resolve the Issue


In line 3, I added an open parenthesis in front of “sales”
as shown below.

160
Good Code
sales = 150.00
days = 31
projectedsales = ((sales/days)*31 )

Reference
These topics from previous chapters are a good reference
for this example.
Chapter 4 - Help()
Chapter 5 - SyntaxError

Ex 7.9 Missing Colon


Description: The colon is misssing. The Console
displays a SyntaxError .

Intended Outcome
Print mylist items to the Console.

Actual Result
When I run the program, there is a SyntaxError.

Incorrect Code
This is the Example 9 code before any changes.
mylist = [‘soda’, ‘water’, ‘coffee’]
for i in range(3)

161
print(mylist[i])

Debugging Steps
The Editor has a red x by line 32 and a yellow triangle
to the left of line 3. When I hover over the yellow triangle, a
pop-up message is displayed, “unexpected indentation.”

How to Resolve the Issue


Line 2 is a “for” statement. I added a colon at the end of
the line.

162
Good Code
mylist = [‘soda’, ‘water’, ‘coffee’]
for i in range(3) :
print(mylist[i])

Reference
These topics from previous chapters are a good reference
for this example.
Chapter 4 - Help()
Chapter 5 - SyntaxError

Ex 7.10 Case Sensitive


Description: Python is case sensitive. Variables with the
wrong case are interpreted as misspelled by the Python
Interpreter and cause a NameError.

Intended Outcome
Print mylist items to the Console.

Actual Result
When I run the program, the Console displays a
NameError.

Incorrect Code

163
In this example, I changed the case on the variable
“myList” with the intention of causing a NameError.

If you previously ran Example 9, “mylist” is still in


memory, and you won’t see a NameError. I wanted to
demonstrate that sometimes you need to reset the
“namespace” to be certain you’re looking at values from
this program.

This is the Example 10 code before any changes.


myList = [‘soda’, ‘water’, ‘coffee’]
for i in range(3) :
print(mylist[i])

Debugging Steps
1. To clear memory (the namespace), in the Consoles
menu, select “Restart kernel.” You could also type %reset
in the Console.
2. When I run the program, the Console displays a
NameError on line 3.

How to Resolve the Issue


On the first line, I change “mylist” to all lowercase.

164
Good Code
mylist = [‘soda’, ‘water’, ‘coffee’]
for i in range(3) :
print(mylist[i])

Reference
These topics from previous chapters are a good reference
for this example.
Chapter 4 - Help()
Chapter 5 - NameError

Ex 7.11 Missing Keyword


Description : A keyword missing when defining a
function causing a SyntaxError.

Intended Outcome
This code creates a new function that adds two numbers
together.

Actual Result
The Editor displays a red “x” to the left of line 1. When I
run the program, the Console Traceback says there is a
SyntaxError on line 1.

165
Figure 7.3 Function with Error

Incorrect Code
This is the Example 11 code before any changes.
myfunction(x, y):
return x+y

Debugging Steps
When looking at line 1, I see that I left off the keyword
“def.” I could also search online for the Python
documentation on defining a function.

How to Resolve the Issue


Add “def ” to the beginning of line 1.

Good Code
def myfunction(x, y):
return x+y

Reference
These topics from previous chapters are a good reference
for this example.
Chapter 5 - Traceback
Chapter 5 - SyntaxError

Ex 7.12 Illegal Character


166
Description: Illegal character in identifier name causes a
SyntaxError.

Intended Outcome
This code creates a string variable.

Actual Result
The program halts with a SyntaxError.

167
Incorrect Code
This is the Example 12 code before any changes.
my$str = ‘hello’
print(my$str)

Debugging Steps
The Editor has a red “x” to the left of line 1, indicating
there is a syntax error in my assignment statement.
Normally, the Editor highlights functions and methods in
purple, and variables are black. The formatting is different
because the Editor is unable to interpret the code.
When I run the program, the Console displays an arrow
pointing to the invalid character in my string name.

Figure 7.4 Invalid Character in the Console

How to Resolve the Issue


Special characters like $, #, and @ are not allowed for
variable names. I rename my variable to “mystr” and the
SyntaxError is resolved.

168
Good Code
mystr = ‘hello’
print(mystr)

Reference
These topics from previous chapters are a good reference
for this example.
Chapter 4 - Help()
Chapter 4 - Debug Mode
Chapter 4 - Interactive Mode
Chapter 5 - NameError
Chapter 5 - SyntaxError

Ex 7.13 Undefined Name


Description : Undefined name when variable is
misspelled. Traceback shows a NameError.

Intended Outcome
Line two calculates profit using the “royalties” variable.

Actual Result
The Editor has a yellow triangle to the left of line 2. When
I run the program the Traceback shows a NameError.

169
Incorrect Code
This is the Example 13 code before any changes.
royalties = 30
profit = royaltie - 2

Debugging Steps
In the Editor, if I click on the variable name, the Editor
highlights all instances of the variable throughout the code. I
assign 300 to the “royalties” variable in line 1. The variable
name is misspelled on line 2.

How to Resolve the Issue


On line 2 I correct the variable name. The Editor pane
highlights all instances of the variable name in yellow, so I
know I am using the variable I intended on line 2.

170
Good Code
royalties = 30
profit = royalties - 2

Reference
These topics from previous chapters are a good reference
for this example.
Chapter 5 - Traceback
Chapter 5 - NameError

Ex 7.14 FileNotFound
Description: While reading a file, the Console halted
with an error “FileNotFoundError.” In this example, factors
outside your control impact your program.

Intended Outcome
This program opens a text file and prints the contents in
the Console.

Actual Result
The Console displays a “FileNotFoundError.”

Incorrect Code
This is the Example 14 code before any changes.

171
file = open(‘file.txt’, ‘r’)
print(file.read())

Debugging Steps
The “FileNotFoundError” has a base class of “IOError.” I
want to check the filename in my OS directory.

1. Import the “os” library to work with the OS commands.


In the Console, type “import os” and then type the list
command, as shown below.

2. Type os.system(‘ls -l’) to see a list of files in the current


directory. The filename has a space in the name. I can
rename the file or updated my program.

How to Resolve the Issue


I decided to rename the file. I did not need to change my
code. I can also add “try” and “except” logic to handle this
type of error.

172
Good Code
file = open(‘file.txt’, ‘r’)
print(file.read())

Reference
These topics from previous chapters are a good reference
for this example.
Chapter 4 - Interactive Mode
Chapter 5 - Traceback
Chapter 5 - RuntimeError
Chapter 5 - OSError (IOError)

Ex 7.15 Error Adding


Numbers
Description: TypeError when adding numbers.

Intended Outcome
Print the total when adding two numbers.

Actual Result
When I run the program, the Console Traceback message
is a TypeError. The code uses “try” and “except” to provide
exception details in the Traceback message. In this example,
the code prints a custom message when there is a TypeError.
The last line prints a custom message if there is another type

173
of Exception.

174
Incorrect Code
This is the Example 15 code before any changes.
eur = ‘euro’
gbp = 8
usd = 3.45
try :
mymoney = eur + usd
print(mymoney)
except TypeError:
print(‘Type error when adding’)
except Exception as strmsg:
print(strmsg)

Debugging Steps
Add the variable information to my print statement and
run the program again.
print(‘Type error when adding; eur’, eur, ‘; usd’, usd)
The Console Traceback shows the variable values. After
reviewing I realize I used “eur” which is a string, and I meant
to use “gbp.”

Figure 7.5 Console Exception Message

Note: I could also have used the “type() ” function to


identify the type of variables.

How to Resolve the Issue


The line assigning a value to “mymoney” is updated to

175
use gbp + usd .

176
Good Code
eur = ‘euro’
gbp = 8
usd = 3.45
try :
mymoney = gbp + usd
print(mymoney)
except TypeError:
print(‘Type error when adding; gbp’, gbp, ‘; usd’, usd)
except Exception as strmsg:
print(strmsg)

Reference
These topics from previous chapters are a good reference
for this example.
Chapter 4 - Print Statements
Chapter 4 - Type()
Chapter 5 - Traceback
Chapter 5 - TypeError

Ex 7.16 Misspelled
Keyword
Description: A misspelled keyword causes a
SyntaxError. This is similar to Example 13 where a variable
name was misspelled causing a NameError.

Intended Outcome
An if-else statement prints a message to the Console.

177
Actual Result
The Editor has a red “x” next to line 4. When I run the
program it halts with a “SyntaxError.”

Incorrect Code
This is the Example 16 code before any changes.
if 4 < 5:
pass
esle:
print(“Python rocks”)

Debugging Steps
There is a typographical error on line3.

How to Resolve the Issue


Update line 3 with the correct spelling of the keyword.

178
Good Code
if 4 < 5:
pass
else:
print(“Python rocks”)

Reference
These topics from previous chapters are a good reference
for this example.
Chapter 4 - Help()
Chapter 5 - Traceback
Chapter 5 - NameError
Chapter 5 - SyntaxError

Ex 7.17 Value is None


Description: The function return value is “None”.

Intended Outcome
My calculation using the “mymath” function return value
prints the result to the Console.

Actual Result
When “i” is 3, the Traceback In the Console , displays a
TypeError .

179
Incorrect Code
This is the Example 17 code before any changes.
def mymath (i=5 , j=200 ):
if i > 3 :
return i*j
if i < 3 :
return j/i
result = mymath(3 , 100 )
print(result/10 )

Debugging Steps
This program works as expected when “i” is any number
except 3.
1. To identify what type the function returns, I use the
type() function in the Console.
In[2] : type(mymath(3,100 ))
Ou t[2]: NoneType
The function returns “None” when “i” is 3.
2. In the Console, I call the “mymath” function again where
“i” is 4. Now the type is “int.” This means that there is a
path through the “mymath” function without a return
value.
In Chapter 3, we looked at a function that did not have a
return value for all paths . For this example, I’m not
going to change the “mymath” function. Instead, I add
logic to my program to handle a “None” value.

How to Resolve the Issue


Add an “if” statement to test for a “None” value.

180
Good Code
def mymath (i=5 , j=200 ):
if i > 3 :
return i*j
if i < 3 :
return j/i
result = mymath(3 , 100 )
if result is not None:
print(result/10 )
else :
print(“result is None” )

Reference
These topics from previous chapters are a good reference
for this example.
Chapter 3 - Function Returns None
Chapter 4 - Interactive Mode
Chapter 5 - Traceback
Chapter 6 - Check Object Type
Chapter 6 - Value is None

Ex 7.18 Method Not Found


Description: AttributeError when the method is not
found.

Intended Outcome
Using the math library, I would like to use a cube
method.

181
Actual Result
When I run the code the Console displays the message
“AttributeError :module ‘math’ has no attribute ‘cube’.”

Incorrect Code
This is the Example 19 code before any changes.
import math
mynum = (.3 , .7 )
mytotal = math.fsum(mynum)
mycube = math.cube(3 )
print(mytotal)

Debugging Steps
I need to see what functions or methods are available for
the math library. In the Editor, after I type “math.” I pause
for a moment. A pop-up opens with available methods, as
shown below.

In the Console, I could also type dir(math) to see a list of


functions/methods in the math library.

How to Resolve the Issue


After scanning the list I see there is no “cube” method
available. I update the code to manually calculate the cube of
“3.”

182
Good Code
import math
mynum = (.3 , .7 )
mytotal = math.fsum(mynum)
mycube = 3 *3 *3
print(mytotal)

Reference
These topics from previous chapters are a good reference
for this example.
Chapter 4 - Help()
Chapter 3 - Tuple
Chapter 4 - Debug Mode
Chapter 4 - Interactive Mode
Chapter 5 - Traceback
Chapter 5 - NameError

Ex 7.19 Module Not Found


Description: ModuleNotFoundError when when the
method is not found.

Intended Outcome
Using the “matplotlib” library I want to plot a chart.

Actual Result
When I run the code, the Console displays
ModuleNotFoundError.

183
Incorrect Code
This is the Example 19 code before any changes.
import matplotlibpyplot as plot
plt.plot([1 , 2 , 3 , 4 ], [25 , 30 , 29 , 31 ])
plt.ylabel(‘age’)
plt.xlabel(‘participants’)
plt.show()

Debugging Steps
I am trying to use the library “matplotlib” plot function,
but am unsure how to import the library. When I search the
Internet for “import matplotlib” I find the correct syntax. In
the help pane, I could search for “mathploglib.pyplot” for
additional details.

How to Resolve the Issue


The first line needs updated to import the correct module.
There is a missing period. After I run the updated program,
In the Console, I can type help(plot.figure(1)) to see
additional information on my new object.
import matplotlib.pyplot as plot

Good Code
import matplotlib.pyplot as plot

184
plot.plot([1 , 2 , 3 , 4 ], [25 , 30 , 29 , 31 ])
plot.ylabel(‘age’)
plot.xlabel(‘participants’)
plot.show()

Reference
These topics from previous chapters are a good reference
for this example.
Chapter 4 - Help()
Chapter 5 - Traceback
Chapter 5 - ModuleNotFound

Ex 7.20 Key Not in


Dictionary
Description: Keyerror. The Key is not in the “wb ”
Dictionary.

Intended Outcome
This program works with an Excel file and formats cells.
Line 11 loops through the rows, and line 12 loops through
the cells of each row. In line 13 I want to set “wrap text” for
the cells.

185
Figure 7.6 20_KeyError.py Script

Actual Result
The program halts and the Traceback In the Console,
displays this error:
KeyError: ‘Worksheet Sheet1 does not exist.’:

186
Incorrect Code
This is the Example 20 code before any changes.
# 20_KeyError.py
from openpyxl import load_workbook, styles
wb = load_workbook(‘before.xlsx’, data_only=True)
ws = wb[“Sheet1”]
ft = styles.Fontt(color=’4F81BD’, bold=True)
ws[‘A1’].font = ft
ws.cell(row=1, column=1).value = ‘Heading 1’
ws.column_dimensions[‘A’].width = 12
for row in ws.iter_rows():
for cell in row:
print(“Looping through data”)

Debugging Experiment
In this Example, when I run the program the program
halts. I use Debug Mode to research what is happening.

1. Run the program. The Python Interpreter halts because of


an exception.
2. In the Console , pane the Traceback displays an error, as
shown below.
KeyError: ‘Worksheet Sheet1 does not exist.’:
3. Type %debug In the Console, pane to start Debug Mode.
The Console prompt changes to ipdb> .
4. While in Debug Mode, In the Console , type “ u ” to step
backward through the program. The Python Interpreter
moves back to the previous call. Now an arrow indicates
the last line of code was line 4 in my 20_KeyError.py
script.

187
ipdb> u
> /20_KeyError.py (4)<module> ()
2 from openpyxl import load_workbook, styles
3 wb = load_workbook(‘before.xlsx’ , data_only=True )
----> 4 ws = wb[“Sheet1” ]
5
6 ft = styles.Fontt(color=’4F81BD’, bold=True)
Line 4 is trying to reference “Sheet1.” Although it’s not
readily apparent, this KeyError indicates this is a
Dictionary key. In the Console, pane, type “ q ” to quit
Debug Mode.
5. Now I need a method to find the sheetnames for the “ wb
” object. In the Console , I use the help command, as
shown below.

Figure 7.7 Help In the Console, Pane

When I scroll down In the Console , pane I see the methods


for the “ wb ” object. A small sample of the output is
shown below. I am interested in the “sheetnames”
method.

Figure 7.8 Details on “wb” Object Methods and Functions

To see the sheetnames for the “wb ” object type


“ws.sheetnames ” In the Console, pane, as shown below.

188
Figure 7.9 The sheetnames Method

The output indicates there is only one worksheet named “


ExportedData ”.

How to Resolve the Issue


When you create a Dictionary named “mydictionary,” it’s
easier to recognize a Dictionary KeyError. Because the
openpyxl created the “ws ” object it’s not as obvious that
this was a Dictionary KeyError. Tuples are immutable, and
any immutable object can be used as a Dictionary key. For
additional information, search the Intranet for help on
openpyxl worksheet objects.
To resolve the error, I update my code to the correct
worksheet name, as shown below.

189
Good Code
In the Editor, I updated line 4 with the sheetname
“ExportedData,” as shown below.
# 20_CORRECT_KeyError.py
from openpyxl import load_workbook, styles
wb = load_workbook(‘before.xlsx’, data_only=True)
ws = wb[“ExportedData”]
ft = styles.Fontt(color=’4F81BD’, bold=True)
ws[‘A1’].font = ft
ws.cell(row=1, column=1).value = ‘Heading 1’
ws.column_dimensions[‘A’].width = 12
for row in ws.iter_rows():
for cell in row:
print(“Looping through data”)

Additional Troubleshooting
In step 4, I wanted more information on
“load_workbook .” The signature function from the Chapter
6 topic, “The Function Call Signature ” would be perfect for
this purpose. With Python v3.x the “signature” lists each
parameter accepted by a function. In the Console, import the
module and print the signature for the object, as shown
below.
In [3]: from inspect import signature
In [4]: print(str(signature(load_workbook)))
(filename, read_only=False, keep_vba=False, data_only=False, keep_links=True)

Reference
These topics from previous chapters are a good reference
for this example.
Chapter 3 - Dictionary
Chapter 3 - Tuple

190
Chapter 4 - Debug Mode
Chapter 4 - Help()
Chapter 5 - Traceback
Chapter 5 - KeyError

Ex 7.21 Incorrect
Argument Type
Description: A function argument is an incorrect type
causing a ValueError.

Intended Outcome
The program asks for a month as input. The int() function
converts the data to an integer so I can use it in a
calculation. The print() function outputs the value to the
Console .

Actual Result
When the program runs, if I enter a string for input, a
ValueError is displayed in the Console . A ValueError is raised
when a function gets an argument of correct type but
improper value.

Incorrect Code
This is the Example 21 code before any changes.
birthmo = int(input(‘what month were you born?’))
monthstogo = 12 - birthmo
print(monthstogo, “months until your birthday”)

191
Debugging Steps
The Traceback shows the program fails on line 1, which
means the variable “birthmo” is not created in memory, and
is not shown in Variable Explorer.
The Traceback message shows ValueError: invalid literal
for int() with base 10: ‘June.’ The string input ‘June’ causes a
ValueError when the int() function tries to convert the string
to an integer.

How to Resolve the Issue


I am going to add “try” and “except” logic to handle the
ValueError exception.

192
Good Code
try:
birthmo = int(input(‘what month were you born?’))
monthstogo = 12 - birthmo
print(monthstogo, “months until your birthday”)
except ValueError:
print(‘enter a number, no letters’)

Reference
These topics from previous chapters are a good reference
for this example.
Chapter 5 - Traceback
Chapter 5 - Try and Except
Chapter 5 - ValueError
Chapter 6 - Check Object Type

Ex 7.22 Name Error


Description: When I try to use “plot” there is a
NameError.

Intended Outcome
Using the “matplotlib” library I want to plot a chart.

Actual Result
When I run the code, the Console displays a NameError
and highlights line 2.

193
Incorrect Code
This is the Example 22 code before any changes.
import matplotlib.pyplot as plot
plt.plot([1 , 2 , 3 , 4 ], [25 , 30 , 29 , 31 ])
plt.ylabel(‘age’)
plt.xlabel(‘participants’)
plt.show()

Debugging Steps
The NameError indicates the object can’t be found. When
I imported the library on line 1, I used “plot,” and on the
other lines I used “plt.”

How to Resolve the Issue


Update line 1 to use “plt.”

Good Code
import matplotlib.pyplot as plt
plt.plot([1 , 2 , 3 , 4 ], [25 , 30 , 29 , 31 ])
plt.ylabel(‘age’)
plt.xlabel(‘participants’)
plt.show()

Reference
These topics from previous chapters are a good reference
for this example.
Chapter 5 - NameError

194
Ex 7.23 Value Error
Descriptio n: Invalid data passed to method causing
ValueError.

Intended Outcome
I want to remove one item from my list.

Actual Result
When the program runs it halts with a ValueError on line
3. A ValueError is raised when a function or method gets an
argument of correct type but improper value.
ValueError: list.remove(x): x not in list

Incorrect Code
This is the Example 23 code before any changes.
fruits = [‘apple’, ‘orange’, ‘grape’]
myfruit = 2
fruits.remove(myfruit)

Debugging Steps
Line 3 uses the “remove” method. I would like to inspect
the list object to see what methods are available.

1. In the Console, type help(fruits) . The interpreter returns


a list of methods available, showing the “remove” uses
the value of a list item.

2. In the Editor, I could position my cursor in front of

195
“remove” and press Cntrl + I. The Help pane displays the
same information on the remove method.

How to Resolve the Issue


Instead of using the value “2”, I update the value of
“myfruit” to “orange.” When I rerun the program there is no
error, and Variable Explorer shows the value “orange” was
removed from my list.

Good Code
fruits = [‘apple’, ‘orange’, ‘grape’]
myfruit = ‘orange’
fruits.remove(myfruit)

Reference
These topics from previous chapters are a good reference
for this example.
Chapter 4 - Interactive Mode
Chapter 4 - Help()
Chapter 5 - ValueError
Chapter 5 - RuntimeError

Ex 7.24 Divide by Zero


196
Error
Description : Calculation causes a ZeroDivisionError.

Intended Outcome
The program retrieves the current GBP exchange rate,
and then converts “gbp” to the equivalent USD value.

Actual Result
When the program runs, a ZeroDivisionError from line 7
is displayed in the Console

197
Incorrect Code
This is the Example 24 code before any changes.
from bs4 import BeautifulSoup
from urllib.request import urlopen
usd, gbp, gbpex = 10.0 , 20.0 , 0.00
html2 = urlopen(‘https://usd.fxexchangerate.com’)
soup2 = BeautifulSoup(html2, ‘lxml’)
tables2 = soup2.findChildren(‘td’)
gbp = gbp/gbpex
print(“gbp converted to USD is:”, gbp)

Debugging Steps
1. Variable Explorer shows the value of “gbpex” is zero.
In this example, I omitted the line to retrieve the GBP
exchange rate.

How to Resolve the Issue


In addition to adding the line of code to retrieve the GBP
exchange rate from a web page, I added code to handle
when “gbpex” causes an exception. In Chapter 4 I also added
logging to handle this type of error.

198
Good Code
from bs4 import BeautifulSoup
from urllib.request import urlopen
usd, gbp, gbpex = 10.0 , 20.0 , 0.00
html2 = urlopen(‘https://usd.fxexchangerate.com’)
soup2 = BeautifulSoup(html2, ‘lxml’)
tables2 = soup2.findChildren(‘td’)
try :
gbpex = float(tables2[3 ].string[:6 ])
gbp = gbp/gbpex
print(“gbp converted to USD is:”, gbp)
except ZeroDivisionError:
print(‘ZeroDivisionError where gbpex is:’, gbpex)

Reference
These topics from previous chapters are a good reference
for this example.
Chapter 4 - Interactive Mode
Chapter 4 - Debug Mode - Variable Explorer
Chapter 4 - Logging
Chapter 5 - Traceback
Chapter 5 - ZeroDivisionError

Ex 7.25 Math Logic Error


Description: There is a logic error in the math
calculation.

Intended Outcome
The math calculation should return 10.

199
Actual Result
The calculation returns 40 instead of 10.

Incorrect Code
This is the Example 25 code before any changes.
myval = 60.0 /3.0 * 2
print(“myval is:”, myval)

Debugging Steps
To ensure multiplication occurs before the division, I add
parentheses to my code.

How to Resolve the Issue


Add parentheses to change the operator precedence .

Good Code
myval = 60.0 /(3.0 * 2)
print(“myval is:”, myval)

Ex 7.26 ValueError
Assigning Date
Description: Operation on incompatible types.
ValueError when assigning a datetime object.

200
Intended Outcome
After creating a datetime object with a date of
12/31/1999, I want to print the value to the Console.

Actual Result
The program halts with a ValueError exception. The
Traceback indicates the error is on line 3.

Incorrect Code
This is the Example 26 code before any changes.
from datetime import datetime
d1 = datetime.strftime(datetime(1999 , 13 , 31 ), ‘%Y-%m-%d’)

Debugging Steps
At a glance I can see that while my intentions were good,
I made a mistake on line 3. It’s obvious there is no month
“13” and the statement on line 3 is invalid. The ValueError In
the Console , also states the “month must be in 1..12.”
When the cause of the ValueError is not obvious, you
could use the Help pane, or search the Internet, to find
correct arguments for a function or method.

How to Resolve the Issue


Line 3 needs updated to use “12” for the month instead of
“13.”

201
Good Code
from datetime import datetime
d1 = datetime.strftime(datetime(1999 , 12 , 31 ), ‘%Y-%m-%d’)

Reference
These topics from previous chapters are a good reference
for this example.
Chapter 4 - Interactive Mode
Chapter 5 - Traceback
Chapter 5 - ValueError
Chapter 6 - Check Arguments
Chapter 6 - Check Function Return Objects

202
Appendix - URLs

Arguments
The Python design and glossary entries for arguments are
shown in this section. Also see Calls, Functions, and
Parameters.
The design of keyword only arguments is covered in PEP
3102:
https://www.python.org/dev/peps/pep-3102/
The Python glossary entry for arguments:
https://docs.python.org/3/glossary.html#term-argument
Python terminology on arguments and parameters:
https://docs.python.org/3.3/library/inspect.html#inspect.Parameter
The difference between Arguments and Parameters:
https://docs.python.org/3/faq/programming.html#faq-
argument-vs-parameter

Assert
The Python reference for assert statements is available on
the docs.ptyhon.org website.
https://docs.python.org/3/reference/simple_stmts.html#the-
assert-statement

203
Attributes
The Python glossary entry for “attributes ” is available on the
docs.ptyhon.org website.
https://docs.python.org/3/glossary.html#term-attribute

Built-in Functions
The Python reference for built-in functions is available on the
docs.ptyhon.org website.
https://docs.python.org/3/library/functions.html

Calls
The Python reference documentation explains “calling”
functions and methods, and is available on the
docs.ptyhon.org website.
https://docs.python.org/3/reference/expressions.html#calls

Classes
Information on Python Classes is available on the
docs.ptyhon.org website.

9.3.2 Instantiation and Attribute References


9.3.3 Instance Objects, Attributes and Methods
9.3.4 Method Objects
9.9 Container Objects, Elements, and Iterators.
https://docs.python.org/2/tutorial/classes.html

204
Comparisons
The following link is the Python reference on comparisons.
https://docs.python.org/3/reference/expressions.html#comparisons

Containers
The docs.ptyhon.org website explains “containers” in the
9.9 section “Container Objects and Iterators.” The section 3.1
topic “Objects, values and types” also explains that objects
that contain references to other objects are containers.
Examples of containers are tuples, lists and dictionaries.
https://docs.python.org/3.8/reference/datamodel.html#index-
3
The 3.1 topic “objects, values, and types” explains that
“container” objects contain references to other objects. This
“Data Model” reference is available on the docs.ptyhon.org
website.
https://docs.python.org/3/reference/datamodel.html#index-
3

doctest
The docs.ptyhon.org website has details on using the
doctest module to search and validate examples in
docstrings.
https://docs.python.org/3/library/doctest.html?
highlight=doctest
Interactive Python examples are also available. These
examples include reading in a text file

205
Functions
The Python reference documentation explains “functions,”
and is available on the docs.ptyhon.org website.
https://docs.python.org/3/reference/compound_stmts.html#function
The Python tutorial for “Defining Functions” is available on
the docs.ptyhon.org website.
https://docs.python.org/3/tutorial/controlflow.html#defining-
functions
https://docs.python.org/3/reference/compound_stmts.html#function-
definitions
The difference between function parameters and arguments
is explained in the FAQs available on the docs.ptyhon.org
website.
https://docs.python.org/3/faq/programming.html#faq-
argument-vs-parameter
The Python glossary entry for “functions” is available on the
docs.ptyhon.org website.
https://docs.python.org/3/glossary.html#term-function

Glossary
The official Python glossary is available on the
docs.ptyhon.org website
https://docs.python.org/3/glossary.html

The if Statement
Information on the if statement is available on the
docs.ptyhon.org website

206
https://docs.python.org/3/reference/compound_stmts.html#the-
if-statement

Immutable
The Python glossary explains the concept of “immutable”
objects, and is available on the docs.ptyhon.org website.
https://docs.python.org/3/glossary.html#term-immutable

Inspect
The Python reference for the “inspect” library is available on
the docs.ptyhon.org website.
https://docs.python.org/3/library/inspect.html

Interactive Mode
Interactive Mode in the Console is explained on the
ipython.readthedocs website.
https://ipython.readthedocs.io/en/stable/interactive/reference.html
.

Iterable and Iterations


The Python glossary explains the “iterable” concept, and is
available on the docs.ptyhon.org website.
https://docs.python.org/3/glossary.html#term-iterable
The docs.ptyhon.org website explains Classes in the 9.9
section “Container Objects and Iterators.”
https://docs.python.org/2/tutorial/classes.html

207
Logging
The Python docs for the “logging library” are available on the
docs.ptyhon.org website.
https://docs.python.org/3/library/logging.html#logging.basicConfig
https://docs.python.org/3.8/howto/logging.html
https://docs.python.org/3/library/logging.html

Magic Functions
Functions that begin with the percent symbol are magic
functions or magic commands and are sometimes
implemented in a iPython kernel. Read more about magic
functions at
https://ipython.readthedocs.io/en/stable/interactive/reference.html
.

Methods
The Python glossary explains “methods,” and is available on
the docs.ptyhon.org website.
https://docs.python.org/3/glossary.html#term-method

Objects
The Python glossary explains “objects,” and is available on
the docs.ptyhon.org website.
https://docs.python.org/3/glossary.html#term-object
Objects like data attributes have value or “state,” and objects
like methods have “defined behavior.”

208
The 3.1 topic “objects, values, and types” in the “Data Model”
reference is available on the docs.ptyhon.org website.
https://docs.python.org/3/reference/datamodel.html#index-
3

Parameters
The Python glossary explains “parameters,” and is available
on the docs.ptyhon.org website.
https://docs.python.org/3/glossary.html#term-parameter
There is information on arguments and parameters in the
“inspect library.”
https://docs.python.org/3.3/library/inspect.html#inspect.Parameter
The difference between Arguments and Parameters is
explained in the FAQs.
https://docs.python.org/3/faq/programming.html#faq-
argument-vs-parameter

The pass Statement


Information on the pass statement is available on the
docs.ptyhon.org website
https://docs.python.org/3/reference/simple_stmts.html#the-
pass-statement

The return Statement


Information on the return statement is available on the
docs.ptyhon.org website
https://docs.python.org/3/reference/simple_stmts.html#the-

209
return-statement

State
The Python glossary explains the “state” of data attributes,
or objects with value.
https://docs.python.org/3/glossary.html#term-object

Statements
The Python glossary explains “statements,” and is available
on the docs.ptyhon.org website.
https://docs.python.org/3/glossary.html#term-statement
https://docs.python.org/3/reference/simple_stmts.html

timeit
Information on the timeit() function is available on the
docs.ptyhon.org website
https://docs.python.org/3/library/timeit.html

The try Statement


Information on the try statement is available on the
docs.ptyhon.org website
https://docs.python.org/3/reference/compound_stmts.html#the-
try-statement

Types
210
The Python glossary explains “types,” and is available on the
docs.ptyhon.org website.
https://docs.python.org/3/glossary.html#term-type
The 3.1 topic “objects, values, and types” in the “Data Model”
reference is available on the docs.ptyhon.org website.
https://docs.python.org/3/reference/datamodel.html#index-
3

Values
The 3.1 topic “objects, values, and types” in the “Data Model”
reference is available on the docs.ptyhon.org website.
https://docs.python.org/3/reference/datamodel.html#index-
3

211
Conclusion

Einstein said, “If you can’t explain it simply, you don’t


understand it well enough.” Learning new things is a passion
of mine, and I’ve found the process of organizing notes,
creating illustrations, and pondering how to craft clear
examples helps me grasp concepts. Then too, it’s nice to go
back in a year when I’ve forgotten something and refer to a
solid example.
Thank you for reading along with me through the
interesting topics and less than thrilling subjects. If the result
is you have mastered new features, it was worth it! I’d love
to hear the cool things you’re doing with Python, so please
don’t hesitate to leave comments in a review.

212
Index
?! = (Not Equal) - See Comparison Operators,
3.14, Appendix Reference
?, 4.8
…: (iPython session), 4.7
%debug, 4.3
<, 3.14, Appendix Reference
< = (Less than or Equal To), 3.14
<=, 3.14, Appendix Reference
==, 3.14, Appendix Reference
>, 3.14, Appendix Reference
>=, 3.14, Appendix Reference
Anaconda, Ch 2
Arbitrary Number of Arguments (see Function,
3.17
Arguments (see Functions), 3.17, 6.9, 7.6,
Appendix Reference
Assert, 5.5
Assign, Ch 3
Assignment statement, Ch 3
Attribute (also see value), 2.19, 3.19,

213
Appendix Reference
Behavior (see Function or Method), Appendix
Reference
Block of Code (See Suite), Ch 3
boolean, 3.6
Breakpoint, 4.5
Call Signature, 4.8, 6.9
Calling a Function, 3.17
Calls, Appendix Reference
Case sensitive , 3.2
Classes, 2.4, Appendix Reference
Code Block, 3.16
Colon, 3.2
Comment, Ch 3
Comparison Operators, 3.14
Console, Ch 2, 4.9
Container, Appendix Reference
Control Statements, 3.15
Convert Data Type, 3.6
Counter, 3.15
Data scrubbing,
Data type, 3.6

214
Debug Mode, 4.3
Define a Function, 3.17
Defined Behavior (see Methods), Appendix
Reference
Dictionary, 3.12
Dir(), 4.8
Divide and Conquer, 4.8, 4.11
DocString (also see Inspect and Signature),
3.18, 4.9
Editor, Ch 2
Elements (see Classes), Appendix Reference
Else Statement, 3.15
Endless Loop, 7.1
Except (see try and except), 5.3
float, 3.6
Focused Testing, 4.11
For Statement, 3.15, 7.20
Functions,
Function Return Values, 3.17
Global Variables, 4.8
help() function, 4.8
id() function, 3.4, 4.9

215
IDE, Ch 2
Identifier (Objects), 3.2, 3.3
If…, 3.15
Immutable, 3.4, 4.9, Appendix Reference
in (see Comparison Operators), 3.14, Appendix
Reference
Increment Counter, 3.15, 4.8
Indentation, 3.16, 4.3
Index, Ch 3
IndexError, 7.1
Infinite Loop, 7.1
Inspect, 3.18, 6.19
Instance (see Classes), Appendix Reference
Instatiation (See Classes), Appendix Reference
integer, 3.6
Integrated Desktop Environment, Ch 2
Interactive Mode, 2.10, 4.1, 4.8
Introspection, 4.8
ipdb prompt, 4.7
iPython Session, 2.10, 4.8
is (see Comparison Operators), 3.14, Appendix
Reference

216
is not (see Comparison Operators), 3.14,
Appendix Reference
Iterable, Appendix Reference
Iterate (Loop), 3.10, 3.15
Keyword Arguments, 3.17
Keywords, 3.2
len (length), 6.8
List Index Out of Range, 7.1
Lists, 3.10
Local Variables, 4.8
Logging, 4.9
Magic Functions, 4.3, 4.8, 5.1
Method (also see Functions), Appendix
Reference
Mutable, Ch 3
Namespace, 4.8
Naming Conventions, Ch 3
Nested, 3.16
None, 3.6, 3.17, 6.6
Not Equal Comparison Operator != , 3.14,
Appendix Reference
not in (see Comparison Operators), 3.14,

217
Appendix Reference
Numbers, 3.7
Objects, 3.3, Appendix Reference
Optional Arguments, 3.17
Parameters, 3.17, Appendix Reference
PEP 3131, 3.2
Plural - Naming Identifiers, 3.2
Positional Arguments, 3.17
Preferences, PEP8,
Prompt (Console), 4.7
Pseudocode, 5.1, 7.35
Python, Ch 2
Raise, 5.4
repr(), string representation (whitespace), 4.8,
7.39
Reserved Keywords, 3.2
Return values, 3.17, 6.10
Run, Ch 2
Scope, 3.4, 4.9
Script, Ch 2
Set, 3.13
Signature (see Inspect), 3.18, 6.19

218
Singular - Naming Identifiers, 3.2
Spaces, also see Whitespace, Ch 3
Special Characters, 3.2
Spyder, Ch 2
State, Appendix Reference
Statements, 3.1, 3.15
str, 3.6
String representation (see repr()), 7.39
Strings, 3.8
Style Guide for Python, see PEP8,
Suite (Block of Code), 3.16, 4.2
Syntax, 3.2
Test data, 4.12
timeit(), 4.10, 5.1
Try and Except statements, 5.3
Tuples, 3.11
Type, 3.6, 6.7, Appendix Reference
Type(), 4.8
Underscore, 3.2, 3.7
Unicode, 3.2
Value, Ch 3
Variable Explorer, 4.54
219
Variables (also see Classes), 2.14, 3.5
While Loop, 3.15, 7.6
Whitespace, 6.6, 7.39

220

You might also like