Module 4
Module 4
1.Calling shutil.copy(source, destination) will copy the file at the path source to the
folder at the path destination.
This function returns a string or Path object of the copied file.
source and destination can be strings or Path objects.) If destination is a filename, it will
be used as the new name of the copied file.
>>> import shutil, os
>>> from pathlib import Path
>>> p = Path.home()
1.>>> shutil.copy(p / 'spam.txt', p / 'some_folder') // the original spam.txt filename is
used for the new,
copied file’s filename.
'C:\\Users\\Al\\some_folder\\spam.txt'
2. >>> shutil.copy(p / 'eggs.txt', p / 'some_folder/eggs2.txt')
WindowsPath('C:/Users/Al/some_folder/eggs2.txt')
//copies the file at C:\Users\Al\eggs.txt to the folder C:\Users\Al\some_folder but gives
the copied file the name eggs2.txt.
The first shutil.copy() call copies the file at C:\Users\Al\spam.txt to the folder C:\Users\
Al\some_folder. The return value is the path of the newly copied file.
3.shutil.copytree() will copy an entire folder and every folder and file contained in
it.
Calling shutil .copytree(source, destination) will copy the folder at the path source, along
with all of its files and subfolders, to the folder at the path destination.
The source and destination parameters are both strings.
The function returns a string of the path of the copied folder.
>>> import shutil, os
>>> from pathlib import Path
>>> p = Path.home()
>>> shutil.copytree(p / 'spam', p / 'spam_backup')
WindowsPath('C:/Users/Al/spam_backup')
The shutil.copytree() call creates a new folder named spam_backup with the same
content as the original spam folder.
import os
for folderName, subfolders, filenames in os.walk('C:\\delicious'): print('The current folder
is ' + folderName)
for subfolder in subfolders:
print('SUBFOLDER OF ' + folderName + ': ' + subfolder)
for filename in filenames:
print('FILE INSIDE ' + folderName + ': '+ filename)
print('')
Since os.walk() returns lists of strings for the subfolder and filename variables,
real example
import os
print("current working directory :{0}".format(os.getcwd()))
os.chdir('E:\\xam22aug') // changed current working directory
for folderName, subfolders, filenames in os.walk('E:\\xam22aug'):
print('The current folder is ' +folderName)
for subfolder in subfolders:
print('SUBFOLDER OF ' + folderName + ': ' +subfolder)
for filename in filenames:
print('FILE INSIDE ' + folderName + ': '+filename)
print('')
Knowing how to create, read, write, and extract ZIP files can be a useful skill for
developers and professionals who work with computers and digital information. Among
other benefits, ZIP files allow you to:
Reduce the size of files and their storage requirements without losing
information
Improve transfer speed over the network due to reduced size and single-file
transfer
Pack several related files together into a single archive for efficient
management
Bundle your code into a single archive for distribution purposes
Secure your data by using encryption, which is a common requirement
nowadays
Guarantee the integrity of your information to avoid accidental and malicious
changes to your data
Your Python programs can created and opened (or extract) ZIP files using functions in
the zipfile module.
we have created a zip file named new.zip compressing contents of path /directory
named D:\python\back\b1\s2.txt
To read the contents of a ZIP file, first you must create a ZipFile object
import zipfile, os
with zipfile.ZipFile("new.zip", mode="r") as archive: // Create a ZipFile object by opening
the ‘new.zip’ in read mode
archive.printdir() // Print the details of ZIP archive to std.out using archive.printdir()
listOfiles = archive.namelist() // get the list of files in it using ZipFile.namelist()
for items in listOfiles: //Iterate over the list of file names in given list
print(items) //& print them
output:
File Name Modified Size
python/back/b1/s2.txt 2023-03-07 05:42:06 300
To create a ZipFile object, call the zipfile.ZipFile() function, passing it a string of the .ZIP
file’s filename.
Note that zipfile is the name of the Python module, and ZipFile() is the name of the
function.
Or
import zipfile
newZip.write('D:\\python\\back\\b1\\s2.txt', compress_type=zipfile.ZIP_DEFLATED)
newZip.close()
The extractall() method for ZipFile objects extracts all the files and folders from a ZIP file
into the current working directory.
>>> import zipfile, os
>>> from pathlib import Path
>>> p = Path.home()
>>> exampleZip = zipfile.ZipFile(p / 'example.zip')
>>> exampleZip.extractall()
>>> exampleZip.close()
After running this code, the contents of example.zip will be extracted to C:\. Optionally,
you can pass a folder name to extractall() to have it extract the files into a folder other
than the current working directory. If the folder passed to the extractall() method does
not exist, it will be created. For instance, if you replaced the call at with
exampleZip.extractall('C:\\ delicious'), the code would extract the files from example.zip
into a newly created C:\delicious folder
Example program
import zipfile, os
from pathlib import Path
p = Path.home()
exampleZip = zipfile.ZipFile('D:\\python\\new.zip')
exampleZip.extractall('D:\\python\\extrt')
exampleZip.close()
Returns a ZipInfo object with information about the member file provided by filename.
Note that filename must hold the path to the target file inside the underlying ZIP file.
ZipFile method to return a ZipInfo object about that particular file. ZipInfo objects have
their own attributes, such as file_size and compress_size in bytes, which hold integers
of the original file size and compressed file size, respectively.
While a ZipFile object represents an entire archive file, a ZipInfo object holds useful
information about a single file in the archive.
example
import zipfile, os
with zipfile.ZipFile("new.zip", mode="r") as archive:
print(archive.namelist())
spam_info = archive.getinfo('python/back/b1/s2.txt')
print(spam_info.file_size)
print(spam_info.compress_size)
print('Compressed file is %sx smaller!' % (round(spam_info.file_size /
spam_info.compress_size, 2)))
//calculates how efficiently new.zip is compressed by dividing the original file size by the
compressed file size and prints this information.
A debugger is a program you can use to better understand where bugs are located in
your code.
What is Debugging?
Debugging is the process of finding and fixing errors or bugs in the source code of any
software. When software does not work as expected, computer programmers study the
messages provide information about what went wrong in your code and can help you
The error message typically includes the type of error that occurred, the line number
By taking the time to understand the error message, you can often quickly identify the
In this example, the error message tells us that a ZeroDivisionError occurred on line 7 of
the main.py file. This error is indicating that a division by zero occurred, which is not
allowed in mathematics. By knowing this information, we can easily fix the error by
Example:
def boxPrint(symbol, width, height): //boxPrint() function that takes a character, a width,
and a height, and uses the character to make a
little picture of a box with that width and height
print(symbol * width)
print(symbol * width)
for sym, w, h in (('*', 4, 4), ('O', 20, 5), ('x', 1, 3), ('ZZ', 3, 3)) : //arguments passed to
boxPrint
try: boxPrint(sym, w, h) //the except Exception as err form of the except statement
print('An exception happened: ' + str(err)) //convert the Exception object to a string by
passing it to str() to produce a user-friendly
error message
output
The traceback includes the error message, the line number of the line that caused the
error, and the sequence of the function calls that led to the error. This sequence of calls
is called the call stack.
Python displays the traceback whenever a raised exception goes unhandled.
Example
def spam():
bacon() //call to bacon() came from line 2,
def bacon():
raise Exception('This is the error message.')
spam()
output
This function is useful if you want the information from an exception’s traceback but also
want an except statement to gracefully handle the exception. You will need to import
Python’s traceback module before calling this function.
you can write the traceback information to a text file and keep your program running.
You can look at the text file later, when you’re ready to debug your program.
Example:
Output:
111
The traceback info was written to errorInfo.txt
The 111 is the return value from the write() method, since 111 characters were written
to the file.
21.Explain Assertion method debuuging
An assertion is a sanity(correctness)check to make sure your code isn’t doing
something obviously wrong. These sanity checks are performed by assert statements. If
the sanity check fails, then an AssertionError exception is raised.
the ages[0] <= ages[-1] expression evaluates to True, the assert statement does
nothing.
let’s assume we had a bug in our code. Say we accidentally called the reverse() list
method instead of the sort() list method. When we enter the following in the interactive
shell, the assert statement raises an AssertionError:
>>> ages = [26, 57, 92, 54, 22, 15, 17, 80, 47, 73]
>>> ages.reverse()
>>> ages [73, 47, 80, 17, 15, 22, 54, 92, 57, 26]
>>> assert ages[0] <= ages[-1] # Assert that the first age is <= the last age.
Or
Logging is a means of tracking events that happen when some software runs. The
software’s developer adds logging calls to their code to indicate that certain events have
occurred
when Python logs an event, it creates a LogRecord object that holds information about
that event. The logging module’s basicConfig() function lets you specify what details
about the LogRecord object you want to see and how you want those details displayed.
Example
import logging
logging.basicConfig(level=logging.DEBUG, format='%(asctime)s - %(levelname)s - %
(message)s')
logging.debug('Start of program')
def factorial(n): logging.debug('Start of factorial(%s%%)' % (n))
total = 1
for i in range(n + 1):
total *= i
logging.debug('i is ' + str(i) + ', total is ' + str(total))
logging.debug('End of factorial(%s%%)' % (n))
return total
print(factorial(5))
logging.debug('End of program')
we use the logging.debug() function when we want to print log information. This debug()
function will call basicConfig(), and a line of information will be printed. This information
will be in the format we specified in basicConfig() and will include the messages we
passed to debug(). The print(factorial(5)) call is part of the original program, so the
result is displayed even if logging messages are disabled.
The output of this program looks like this:
2019-05-23 16:20:12,664 - DEBUG - Start of program
2019-05-23 16:20:12,664 - DEBUG - Start of factorial(5)
2019-05-23 16:20:12,665 - DEBUG - i is 0, total is 0
2019-05-23 16:20:12,668 - DEBUG - i is 1, total is 0
2019-05-23 16:20:12,670 - DEBUG - i is 2, total is 0
2019-05-23 16:20:12,673 - DEBUG - i is 3, total is 0
2019-05-23 16:20:12,675 - DEBUG - i is 4, total is 0
2019-05-23 16:20:12,678 - DEBUG - i is 5, total is 0
2019-05-23 16:20:12,680 - DEBUG - End of factorial(5) 0
2019-05-23 16:20:12,684 - DEBUG - End of program
The factorial() function is returning 0 as the factorial of 5, which isn’t right. The for loop
should be multiplying the value in total by the numbers from 1 to 5. But the log
messages displayed by logging.debug() show that the i variable is starting at 0 instead
of 1. Since zero times anything is zero, the rest of the iterations also have the wrong
value for total. Logging messages provide a trail of breadcrumbs that can help you
figure out when things started to go wrong. Change the for i in range(n + 1): line to for i
in range(1, n + 1):, and run the program again.
DEBUG,
INFO,
WARNING,
ERROR,
And CRITICAL.
WARNING is a default stage, meaning only messages with a group of WARNING or
higher will be logged.
You can change the logging level to DEBUG to see all messages or to ERROR to
only see notes with a level of ERROR or higher.
import logging
logging.warning('Watch out!') # will print a message to the console
logging.info('I told you so') # will not print anything
If you type these lines into a script and run it, you’ll see:
WARNING:root:Watch out!
printed out on the console. The INFO message doesn’t appear because the default
level is WARNING. The printed message includes the indication of the level and the
description of the event provided in the logging call, i.e. ‘Watch out!’.
28.
IDLE has a debugger built into it. It is very useful for stepping through a program and
watching the variables change values.
The background of the line you click on turns yellow to show the line marked with the
breakpoint.
If you don't put any breakpoints in your source, when you run it with the debugger on,
it will pause at the first line of executable code (may be an import statement or a call
to main()) but then will run your program normally (i.e. with no pauses).
From this point you can click the Go button near the top of the window. This will
make the program run at normal speed until a breakpoint is encountered (or input is
requested or the program finishes). You can also use the Step button to step through
your code, one line at a time. This button is used quite a lot. If the line being stepped
through has a function call, execution will go to the first line of the function definition
(you are "stepping into" the function). If the line being stepped through doesn't have a
function call, the line is executed. In either case, then control goes back to the human.
When you execute a line that has input in it, the debugger seems to shut down but it
has not. If you bring up the Shell window you can see that the program is waiting for
input. Make sure your cursor is in the right place on the window and give it some
input and press Enter as usual.
There are several things to note about this picture. The Shell window is in the
background, it shows that the user entered 23 and pressed Enter. The Debug Control
window shows that execution has moved on to the next line of code. Also, at the
bottom of that window there is a pane that says "Locals" and it shows the value of
radius to be '23'. This is useful in several ways. It shows the values of variables as
they change, and it shows the types of variables. Note that the value of radius has
quotes around it. This means that it is a string value.
"You can only toggle the debugger when idle" If you get this message in a window
when you try to turn the debugger on, try clicking on the Quit button in the Debug
Control window. If that does not help, try shutting down the program file and
reopening it. If that does not help, shut down Python completely and restart it from
scratch.
Note that the bugs in the input statements have been fixed with the addition of "eval".
The breakpoint was put in again. Breakpoint locations are not saved with the program;
they have to be set again for every debugging session.
Note the type of the Local variables in this image. They don't have the quotes around
the values any more! They are numbers now.
As you step through the program one statement at a time, you can see more variables
get values. When we come to the next bug you can see that the variable Pi is not the
same as the variable pi, which is defined in the math library. This bug would need to
be fixed, then the debugging would continue.
So the process of using the debugger involves
setting breakpoints
stepping through the source code one line at a time
inspecting the values of variables as they change
making corrections to the source as bugs are found
rerunning the program to make sure the fixes are correct
Over means that if the statement to be executed has a function call in it, go off
and do the function call without showing any details of the execution or
variables, then return and give the human control again, "step over the
function"
Out assumes you are in some function's code, finish execution of the function
at normal speed, return from the function and then give the human control
again, "step out of the function"
Quit stops the execution of the entire program
If you enter the wrong code, the computer won’t give you the right program. A computer program will
always do what you tell it to, but what you tell the program to do might not be the same as what
you wanted the program to do. These errors are bugs in a computer program. Bugs happen when the
programmer has not carefully thought about what exactly the program is doing. There are three types of
bugs that can happen with your program:
Syntax Errors are a type of bug that comes from typos. When the Python interpreter sees a syntax
error, it is because your code isn’t written in proper Python language. A Python program with
even a single syntax error won’t run.
Runtime Errors are bugs that happen while the program is running. The program will work up
until it reaches the line of code with the error, and then the program terminates with an error
message (this is called crashing). The Python interpreter will display a “traceback” and show the
line where the problem happens.
Semantic Errors are the trickiest to fix. These bugs don’t crash the program, but it isn’t doing
what the programmer intended for the program to do. For example, if the programmer wants the
variable total to be the sum of the values in variables a, b, and c but writes total = a * b * c, then the
value in total will be wrong. This could crash the program later on, but it is not immediately
obvious where the semantic bug happened.
Finding bugs in a program can be hard, if you even notice them at all! When running your program, you
may discover that sometimes functions are not called when they are supposed to be, or maybe they are
called too many times. You may code the condition for a while loop wrong, so that it loops the wrong
number of times. (A loop in your program that never exits is a kind of bug called an infinite loop. To stop
this program, you can press Ctrl-C in the interactive shell to terminate the program.) Any of these things
could mistakenly happen in your code if you are not careful.
In fact, from the interactive shell, go ahead and create an infinite loop by typing this code in (you have to
press ENTER twice to let the interactive shell know you are done typing in the while-block:
>>> while True:
... print('Press Ctrl-C to stop this infinite loop!!!')
...
Now press and hold down the Ctrl key and press the C key to stop the program. The interactive shell will
look like this:
Press Ctrl-C to stop this infinite loop!!!
Press Ctrl-C to stop this infinite loop!!!
Press Ctrl-C to stop this infinite loop!!!
Press Ctrl-C to stop this infinite loop!!!
Press Ctrl-C to stop this infinite loop!!!
Traceback (most recent call last):
File "<pyshell#1>", line 1, in <module>
while True: print('Press Ctrl-C to stop this infinite loop!!!')
KeyboardInterrupt
The Debugger
It can be hard to figure out how your code could be causing a bug. The lines of code get executed quickly
and the values in variables change so often. A debugger is a program that lets you step through your code
one line at a time in the same order that Python executes them. The debugger also shows you what values
are stored in variables at each step.
Starting the Debugger
In IDLE, open the Dragon Realm game you made in the last chapter. After opening the dragon.py file,
click on the Debug ► Debugger to make the Debug Control window appear (Figure 7-1).
Now when you run the Dragon Realm game by pressing F5, IDLE’s debugger will activate. This is called
running a program “under a debugger”. In the Debug Control window, check
the Source and Globals checkboxes.
When you run Python programs under the debugger, the program will stop before it executes the first
instruction. If you click on the file editor window's title bar (and you’ve checked the Source checkbox in
the Debug Control window), the first instruction is highlighted in gray. The Debug Control window
shows the execution is on line 1, which is the import random line.
Stepping
The debugger lets you execute one instruction at a time. This is called stepping. To execute a single
instruction, click the Step button in the Debug Window. Go ahead and do this now. Python will execute
the import random instruction, and then stop before it executes the next instruction. The Debug Control
window will show the execution is now on line 2, the import time line. Click the Quit button to terminate
the program for now.
Here is a summary of what happens when you click the Step button when you run the Dragon Realm
game under a debugger. Press F5 to start running Dragon Realm again, then follow these instructions:
1. Click the Step button twice to run the two import lines.
2. Click the Step button three more times to execute the three def statements.
3. Click the Step button again to define the playAgain variable.
4. Click Go to run the rest of the program, or click Quit to terminate the program.
The Debug Control window will show you what line is about to be executed when you click the Step
button in the Debug Control window. The debugger skipped line 3 because it’s a blank line. Notice you
can only step forward with the debugger, you cannot go backwards.
Globals Area
The Globals area in the Debug Control window is where all the global variables can be seen. Remember,
global variables are the variables that are created outside of any functions (that is, in the global scope).
As the three def statements execute and define functions, they will appear in the Globals area of the Debug
Control window.
The text next to the function names in the Globals area will look like “<function checkCave at
0x012859B0>“. The module names also have confusing looking text next to them, such as “<module
'random' from 'C:\\Python31\\lib\\random.pyc'>“. You don’t need to know what it means to debug your
programs. Just seeing that the functions and modules are there in the Global area will tell you if the
function has been defined or the module has been imported.
You can also ignore the __builtins__, __doc__, and __name__ lines in the Global area. (Those are variables
that appear in every Python program.)
When the playAgain variable is created it will show up in the Global area. Next to the variable name will be
the string 'yes'. The debugger lets you see the values of all the variables in the program as the program
runs. This is useful for fixing bugs.
Locals Area
There is also a Locals area, which shows you the local scope variables and their values. The local area
will only have variables in it when the program execution is inside of a function. When the execution is in
the global scope, this area is blank.
When the execution is paused at line 5, clicking Step one more time will step into the print() function.
The print() function is one of Python’s built-in functions, so it isn’t useful to step through with the
debugger. Python’s own functions such as print(), input(), str(), or random.randint() have been carefully
checked for errors. You can assume they’re not the parts causing bugs in your program.
So you don’t want to waste time stepping through the internals of the print() function. So instead of
clicking Step to step into the print() function’s code, click Over. This will step over the code inside
the print() function. The code inside print() will be executed at normal speed, and then the debugger will
pause once the execution returns from print().
Stepping over is a convenient way to skip stepping through code inside a function. The debugger will
now be paused at line 40, caveNumber = chooseCave().
Click Step one more time to step into the chooseCave() function. Keep stepping through the code until line
15, the input() call. The program will wait until you type a response into the interactive shell, just like
when you run the program normally. If you try clicking the Step button now, nothing will happen because
the program is waiting for a keyboard response.
Click back on the interactive shell window and type which cave you want to enter. The blinking cursor
must be on the bottom line in the interactive shell before you can type. Otherwise the text you type will
not appear.
Once you press ENTER, the debugger will continue to step lines of code again. Click the Out button on
the Debug Control window. This is called stepping out, because it will cause the debugger to step over as
many lines as it needs to until execution has returned from the function it is in. After it jumps out, the
execution will be on the line after the line that called the function.
For example, clicking Out inside the displayIntro() function on line 6 would step until the function returned
to the line after the call to displayIntro(). Stepping out can save you from having to click Step repeatedly to
jump out of the function.
If you are not inside a function, clicking Out will cause the debugger will execute all the remaining lines
in the program. This is the same behavior as clicking the Go button.
Here’s a recap of what each button does:
Go - Executes the rest of the code as normal, or until it reaches a break point. (Break points are
described later.)
Step - Step one instruction. If the line is a function call, the debugger will step into the function.
Over - Step one instruction. If the line is a function call, the debugger won’t step into the
function, but instead step over the call.
Out - Keeps stepping over lines of code until the debugger leaves the function it was in
when Out was clicked. This steps out of the function.
Quit - Immediately terminates the program.
Type the program as it is above, even if you can already tell what the bug is. Then trying running the
program by pressing F5. This is a simple arithmetic quiz that comes up with two random numbers and
asks you to add them. Here’s what it might look like when you run the program:
What is 5 + 1?
6
Nope! The answer is 6
That’s a bug! The program doesn’t crash but it is not working correctly. The program says the user is
wrong even if they type the correct answer.
Running the program under a debugger will help find the bug’s cause. At the top of the interactive shell
window, click on Debug ► Debugger to display the Debug Control window. In the Debug Control
window, check all four checkboxes (Stack, Source, Locals, and Globals). This makes the Debug Control
window provide the most information. Then press F5 in the file editor window to run the program. This
time it will be run under the debugger.
1. import random
The debugger starts at the import random line. Nothing special happens here, so just click Step to execute it.
You will see the random module added to the Globals area.
2. number1 = random.randint(1, 10)
Click Step again to run line 2. A new file editor window will appear with the random.py file. You have
stepped inside the randint() function inside the random module. Python’s built-in functions won’t be the
source of your bugs, so click Out to step out of the randint() function and back to your program. Then close
the random.py file's window.
3. number2 = random.randint(1, 10)
Next time, you can click Over to step over the randint() function instead of stepping into it. Line 3 is also
a randint() function call. Skip stepping into this code by clicking Over.
4. print('What is ' + str(number1) + ' + ' + str(number2) + '?')
Line 4 is a print() call to show the player the random numbers. You know what numbers the program will
print even before it prints them! Just look at the Globals area of the Debug Control window. You can see
the number1 and number2 variables, and next to them are the integer values stored in those variables.
The number1 variable has the value 4 and the number2 variable has the value 8. When you click Step, the
program will display the string in the print() call with these values. The str() function will concatenate the
string version of these integers. When I ran the debugger, it looked like Figure 7-4. (Your random
numbers will probably be different.)
Clicking on Step from line 5 will execute input(). The debugger waits until the player enters a response
into the program. Enter the correct answer (in my case, 12) into the interactive shell window. The
debugger will resume and move down to line 6.
6. if answer == number1 + number2:
7. print('Correct!')
Line 6 is an if statement. The condition is that the value in answer must match the sum
of number1 and number2. If the condition is True, then the debugger will move to line 7. If the condition
is False, the debugger will move to line 9. Click Step one more time to find out where it goes.
8. else:
9. print('Nope! The answer is ' + str(number1 + number2))
The debugger is now on line 9! What happened? The condition in the if statement must have been False.
Take a look at the values for number1, number2, and answer. Notice that number1 and number2 are integers, so
their sum would have also been an integer. But answer is a string.
That means that answer == number1 + number2 would have evaluated to '12' == 12. A string value and an
integer value will always not equal each other, so the condition evaluated to False.
That is the bug in the program. The bug is that the code has answer when it should have int(answer). Change
line 6 to int(answer) == number1 + number2, and run the program again.
What is 2 + 3?
5
Correct!
This time, the program worked correctly. Run it one more time and enter a wrong answer on purpose.
This will completely test the program. You’ve now debugged this program! Remember, the computer will
run your programs exactly as you type them, even if what you type isn’t what you intend.
Break Points
Stepping through the code one line at a time might still be too slow. Often you’ll want the program to run
at normal speed until it reaches a certain line. A break point is set on a line when you want the debugger
to take control once execution reaches that line. If you think there’s a problem with your code on, say,
line 17, just set a break point on line 17 (or maybe a few lines before that).
When execution reaches that line, the debugger will “break into the debugger”. Then you can step
through lines one at a time to see what is happening. Clicking Go will execute the program normally until
it reaches another break point or the end of the program.
To set a break point, right-click on the line in the file editor and select Set Breakpoint from the menu that
appears. The file editor will highlight that line with yellow. You can set break points on as many lines as
you want. To remove the break point, click on the line and select Clear Breakpoint from the menu that
appears.
Figure 7-5: The file editor with two break points set.
The program runs pretty fast. It spent more time waiting for the user to press ENTER than doing the coin
flips. Let’s say you wanted to see it do coin flips one by one. On the interactive shell's window, click
on Debug ► Debugger to bring up the Debug Control window. Then press F5 to run the program.
The program starts in the debugger on line 1. Press Step three times in the Debug Control window to
execute the first three lines (that is, lines 1, 2, and 3). You’ll notice the buttons become disabled
because input() was called and the interactive shell window is waiting for the user to type something. Click
on the interactive shell window and press ENTER. (Be sure to click beneath the text in the interactive
shell window, otherwise IDLE might not receive your keystrokes.)
You can click Step a few more times, but you’ll find that it would take quite a while to get through the
entire program. Instead, set a break point on lines 12, 14, and 16. The file editor will highlight these lines
as shown in Figure 7-6.
After setting the breakpoints, click Go in the Debug Control window. The program will run at normal
speed until it reaches the next break point. When flip is set to 100, the condition for the if statement on line
13 is True. This causes line 14 (where there’s a break point set) to execute, which tells the debugger to
stop the program and take over. Look at the Debug Control window in the Globals section to see what the
value of flips and heads are.
Click Go again and the program will continue until it reaches the next break point on line 16. Again, see
how the values in flips and heads have changed.
If you click Go again, the execution will continue until the next break point is reached, which is on line
12.
Summary
Writing programs is only the first part of programming. The next part is making sure the code you wrote
actually works. Debuggers let you step through the code one line at a time. You can examine which lines
execute in what order, and what values the variables contain. When this is too slow, you can set break
points to stop the debugger only at the lines you want.
Using the debugger is a great way to understand what a program is doing. While this book provides
explanations of all the game code in it, the debugger can help you find out more on your own.