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

Module 4

The document explains various functions and methods available in the shutil and zipfile modules of Python for working with files and directories. It covers topics like copying, moving, deleting files and folders, compressing files into zip archives, reading and extracting zip files.

Uploaded by

ppl.gecbidar
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
24 views

Module 4

The document explains various functions and methods available in the shutil and zipfile modules of Python for working with files and directories. It covers topics like copying, moving, deleting files and folders, compressing files into zip archives, reading and extracting zip files.

Uploaded by

ppl.gecbidar
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 39

Module-4

1.Explain The shutil module”


The shutil (or shell utilities) module has functions to let you copy, move, rename, and
delete files in your Python programs.
Or
Shutil module offers high-level operation on a file like a copy, create, and remote
operation on the file. It comes under Python’s standard utility modules. This module
helps in automating the process of copying and removal of files and directories

1.Copying files and folders


2. Moving and Renaming Files and Folders
3. Permanently Deleting Files and Folders
4. Safe Deletes with the send2trash Module

2.Explain .Copying files and folders

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.

4. Moving and Renaming Files and Folders

Calling shutil.move(source, destination)


will move the file or folder at the path source to the path destination and will return a
string of the absolute path of the new location.
If destination points to a folder, the source file gets moved into destination and keeps its
current filename
>>> import shutil
>>> shutil.move('C:\\bacon.txt', 'C:\\eggs')
'C:\\eggs\\bacon.txt'
Assuming a folder named eggs already exists in the C:\ directory,
this shutil.move() call says, “Move C:\bacon.txt into the folder C:\eggs.”
If there had been a bacon.txt file already in C:\eggs, it would have been overwritten.
Since it’s easy to accidentally overwrite files in this way,
you should take some care when using move().
The destination path can also specify a filename.
In the following example, the source file is moved and renamed.
>>> shutil.move('C:\\bacon.txt', 'C:\\eggs\\new_bacon.txt')
'C:\\eggs\\new_bacon.txt'
This line says, “Move C:\bacon.txt into the folder C:\eggs,
and while you’re at it, rename that bacon.txt file to new_bacon.txt.”
In above example it was assumed that their was an folder eggs.
But if there is no eggs folder, then move() will rename bacon.txt to a file named eggs
>>> shutil.move('C:\\bacon.txt', 'C:\\eggs') //
'C:\\eggs'
Here, move() can’t find a folder named eggs in the C:\ directory
so assumes that destination must be specifying a filename, not a folder.
the bacon.txt text file is renamed to eggs (a text file without the .txt file extension)
>>> shutil.move('spam.txt', 'c:\\does_not_exist\\eggs\\ham')
Traceback (most recent call last): --snip-- FileNotFoundError: [Errno 2] No such file or
directory: 'c:\\does_not_exist\\ eggs\\ham'
It doesn’t find the nonexistent directory, so it can’t move spam.txt to the path specified.
5.what are the functions to Permanently Delete Files and Folders
Delete a single file or a single empty folder with functions in the os module, whereas to
delete a folder and all of its contents, we use the shutil module.

• Calling os.unlink(path) will delete the file at path.


• Calling os.rmdir(path) will delete the folder at path. This folder must be empty of any
files or folders.
• Calling shutil.rmtree(path) will remove the folder at path, and all files and folders it
contains will also be deleted
6.How to avoid the situations of accidental deletion of files or folders with
example.
To first run your program with function to delete files /folders calls commented out and
with print() calls added to show the files that would be deleted.
Here in the below example program that was intended to delete files that have the .txt
file extension
but it delete .rxt files instead:
import os
from pathlib import Path
for filename in Path.home().glob('*.rxt'):
os.unlink(filename)

I files ending with .rxt, have been accidentally, permanently deleted


Instead, first run the program like this:
import os
from pathlib import Path
for filename in Path.home().glob('*.rxt'):
#os.unlink(filename)
print(filename)

Now the os.unlink() call is commented, so Python ignores it


the program first will show you that you’ve accidentally told the program to delete .rxt
files instead of .txt files
After getting confirmation that the program works as intended, delete the print(filename)
line and uncomment the os.unlink(filename) line. Then run the program again to and
then actual file is deleted.
7.How to delete the files Safely with the send2trash Module.
Using send2trash is much safer than Python’s regular delete functions, because it will
send folders and files to your computer’s trash or recycle bin instead of permanently
deleting them.
If a bug in your program deletes something with send2trash you didn’t intend to delete,
you can later restore it from the recycle bin.
it will not free up disk space like permanently deleting them does
Install send2trashb from running pip install --user send2trash from a Terminal window,
enter the following into the interacative shell:
>>> import send2trash
>>> baconFile = open('bacon.txt', 'a') # creates the file
>>> baconFile.write('Bacon is not a vegetable.')
25
>>> baconFile.close()
>>> send2trash.send2trash('bacon.txt')

8.Explain how to Walk a Directory Tree


the os.walk() function on the directory tree from Figure

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,

When you run this program, it will output the following:


The current folder is C:\delicious
SUBFOLDER OF C:\delicious: cats SUBFOLDER OF
C:\delicious: walnut
FILE INSIDE C:\delicious: spam.txt

The current folder is C:\delicious\cats


FILE INSIDE C:\delicious\cats: catnames.txt
FILE INSIDE C:\delicious\cats: zophie.jpg

The current folder is C:\delicious\walnut


SUBFOLDER OF C:\delicious\walnut: waffles

The current folder is C:\delicious\walnut\waffles


FILE INSIDE C:\delicious\walnut\waffles: butter.txt.

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('')

9.what are zip files


File which can hold the compressed contents of many other files
A ZIP file can also contain multiple files and subfolders, it’s a handy way to package
several files into one.
10.what is file compressing
Compressing a file reduces its size, which is useful when transferring it over the internet

11. Why Use ZIP Files?

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

12. explain Compressing Files with the zipfile Module.

Your Python programs can created and opened (or extract) ZIP files using functions in
the zipfile module.

import zipfile //import the module,


from pathlib import Path
newZip = zipfile.ZipFile('new.zip', 'w')
newZip.write('D:\\python\\back\\b1\\s2.txt', compress_type=zipfile.ZIP_DEFLATED)
newZip.close()
print('created zip file for above mentioned path')

we have created a zip file named new.zip compressing contents of path /directory
named D:\python\back\b1\s2.txt

>>> spamInfo = exampleZip.getinfo('spam.txt')


>>> spamInfo.file_size
13908
>>> spamInfo.compress_size
3828
>>> f'Compressed file is {round(spamInfo.file_size / spamInfo .compress_size, 2)}x
smaller!' ) 'Compressed file is 3.63x smaller!'
>>> exampleZip.close()

13.How to read zip files explain

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

14.How to create zip files

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.

>>> import zipfile, os //importing zipfile from os module


>>> from pathlib import Path //importing pathlib from Path module
>>> p = Path.home() //p assigned with path list of home directory
>>> exampleZip = zipfile.ZipFile(p / 'example.zip') //zipfile function converting file in
the path to
zip file storing in the name
example.zip
>>> exampleZip.namelist()

['spam.txt', 'cats/', 'cats/catnames.txt', 'cats/zophie.jpg'] //printing list of example.zip files


path

Or

import zipfile

from pathlib import Path

newZip = zipfile.ZipFile('new.zip', 'w')

newZip.write('D:\\python\\back\\b1\\s2.txt', compress_type=zipfile.ZIP_DEFLATED)

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

newZip.close()

15. explain what is Extracting from ZIP Files


The extract() method for ZipFile objects will extract a single file from the ZIP file.
>>> exampleZip.extract('spam.txt')
'C:\\spam.txt'

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()

16. explain getinfo method of python

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.

17.Define debugger,debugging in python

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

code to determine why any errors occurred.

Understanding error messages is a key part of effective debugging in Python. Error

messages provide information about what went wrong in your code and can help you

identify and fix the problem.

The error message typically includes the type of error that occurred, the line number

where the error occurred, and a description of the problem.

By taking the time to understand the error message, you can often quickly identify the

root cause of the problem and fix it.

Here is an example of a common error message in Python:


File "main.py", line 7, in <module>
print(5 / 0)
ZeroDivisionError: division by zero

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

ensuring that we do not divide by zero.

18.Explain raising exceptions technique of debugging with an example.

Python raises an exception whenever it tries to execute invalid code.


Raising an exception is a way of saying, “Stop running the code in this function and
move the program execution to the except statement.” Exceptions are raised with a
raise statement. In code, a raise statement consists of the following:

• The raise keyword


• A call to the Exception() function
• A string with a helpful error message passed to the Exception() function

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

if len(symbol) != 1: //if statements to raise exceptions i.e symbol must


of single character

raise Exception('Symbol must be a single character string.') //exception raised

if width <= 2: //if width is not greater than 2

raise Exception('Width must be greater than 2.') //raised exception

if height <= 2: //if height is not greater than 2


raise Exception('Height must be greater than 2.') //raised exception

print(symbol * width)

for i in range(height - 2):

print(symbol + (' ' * (width - 2)) + symbol)

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

except Exception as err:

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

19.Explain traceback method of debugging.

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

Traceback (most recent call last):


File "errorExample.py", line 7, in <module>
spam()
File "errorExample.py", line 2, in spam //call to bacon() came from line 2,
bacon()
File "errorExample.py", line 5, in bacon //the error happened on line 5, in the bacon()
function.
raise Exception('This is the error message.')
Exception: This is the error message.

20.Explain traceback.format_exc(). Function with example used for Getting the


Traceback as a String.

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:

>>> import traceback


>>> try:
... raise Exception('This is the error message.')
except:
... errorFile = open('errorInfo.txt', 'w')
... errorFile.write(traceback.format_exc())
... errorFile.close()
... print('The traceback info was written to errorInfo.txt.')

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.

an assert statement consists of the following:


• The assert keyword
• A condition (that is, an expression that evaluates to True or False)
• A comma
• A string to display when the condition is False In plain English, an assert statement
says, “I assert that the condition holds true, and if not, there is a bug somewhere, so
immediately stop the program.” For example,
>>> ages = [26, 57, 92, 54, 22, 15, 17, 80, 47, 73]
>>> ages.sort()
>>> ages [15, 17, 22, 26, 47, 54, 57, 73, 80, 92]
>>> assert ages[0] <= ages[-1]
# Assert that the first age is <= the last age.
The assert statement here asserts that the first item in ages should be less than or
equal to the last one. This is a sanity check;
if the code in sort() is bug-free and did its job, then the assertion would be true.

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.

Traceback (most recent call last):


File "stdin", line 1, in<module>
AssertionError

Assertions are for programmer errors, not user errors.


You shouldn’t use assert statements in place of raising exceptions, because users can
choose to turn off assertions.
Assertions also aren’t a replacement for comprehensive testing.

22. What Is Python Logging?


Python logging is a module that allows you to track events that occur while your
program is running. You can use logging to record information about errors, warnings,
and other events that occur during program execution. And logging is a useful tool for
debugging, troubleshooting, and monitoring your program.

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

23.Explain logging method of debugging


Python’s logging module makes it easy to create a record of custom messages that you
write. These log messages will describe when the program execution has reached the
logging function call and list any variables you have specified at that point in time. On
the other hand, a missing log message indicates a part of the code was skipped and
never executed.

import logging logging


.basicConfig(level=logging.DEBUG, format=' %(asctime)s - %(levelname) s - %
(message)s')

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.

The output will look like this:


2019-05-23 17:13:40,650 - DEBUG - Start of program
2019-05-23 17:13:40,651 - DEBUG - Start of factorial(5)
2019-05-23 17:13:40,651 - DEBUG - i is 1, total is 1
2019-05-23 17:13:40,654 - DEBUG - i is 2, total is 2
2019-05-23 17:13:40,656 - DEBUG - i is 3, total is 6
2019-05-23 17:13:40,659 - DEBUG - i is 4, total is 24
2019-05-23 17:13:40,661 - DEBUG - i is 5, total is 120
2019-05-23 17:13:40,661 - DEBUG - End of factorial(5) 120
2019-05-23 17:13:40,666 - DEBUG - End of program
The factorial(5) call correctly returns 120.
The log messages showed what was going on inside the loop, which led straight to the
bug.

24.Explain debugging levels


Python logging levels are used to indicate the severity of a message. There are five
logging levels in Python:

 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.

A very simple example is:

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!’.

25. Benefits of Logging in Python


Python logging is a powerful tool that can help you debug your code and track errors.
When used correctly, it can provide valuable insights into what your code is doing and
where it is failing.
And logging can be used to monitor your code's performance and identify potential
bottlenecks.
Overall, python logging is a valuable tool that every python developer should be familiar
with.

26. note on Stack Traces


A stack trace is a report of the active stack frames at a certain point during the
execution of a program. With the help of stack trace, we can determine where the
program was when it crashed, and stack trace can be used to trace the path of
execution through the program. And there are a few ways to capture stack traces.
The most common way is to use a debugger. A debugger is a program that steps
through code, examines variables, and sets breakpoints. When a breakpoint is reached,
the debugger will stop execution and print out the current stack trace.
Another way to capture stack traces is to use a logging framework.
27. Why Printing is not a good option?
Some developers use the concept of printing the statements to validate if the
statements are executed correctly or some error has occurred. But printing is not a good
idea. It may solve your issues for simple scripts but for complex scripts, the printing
approach will fail.
Python has a built-in module logging which allows writing status messages to a file or
any other output streams. The file can contain the information on which part of the code
is executed and what problems have been arisen.

28.

Assertions are used,


1. When you want to stop the program immediately rather to proceed with an
unwanted state.
2. When there are certain possibilities of cascading failures (i.e. in microservices) for
the first unexpected condition that might lead the application into severe
inconsistent or unrecoverable states.
3. When you want to detect bugs in your system exclusively in the debugging period.
You might want to disable them in production if language supports.
4. When you already know that the unexpected conditions arose due to your internal
miss-implementation and external system (i.e the callers) has no control over the
unwanted state.

Exceptions are used,


1. When you know that the unexpected conditions arose due to external systems fault
(i.e. wrong parameters, lack of resources etc).
2. When you know that the conditions can be backed up with alternative paths
keeping the application functional qualities still intact (i.e. might work well for
another call with proper parameters from the caller or external system).
3. When you want to log and let the developers know about some unwanted state but
not a big deal.

29.Explain IDLE’s Debuuger


The IDLE (Integrated Development and Learning Environment) debugger is
basically PDB with buttons and controls on a window, for those who prefer a more
visual tool.
The overall debugging process is:
Set breakpoints
Go through your code line-by-line checking variables and values
Fix any errors that might appear
Re-run the code and check if everything is ok, if not, go back to step 1.
Let’s see how to perform these steps on IDLE.

Debugging under IDLE

IDLE has a debugger built into it. It is very useful for stepping through a program and
watching the variables change values.

Start IDLE and open this program source file.


In the Shell window, click on the Debug menu option at the top and then on
Debugger. You will see a "Debug Control" window like this

Notice that the Shell shows "[DEBUG ON]".


For the debugger to be most useful, you need to set a breakpoint in your source code
before you start running the program. A breakpoint is a marker on your code that tells
the debugger "run to this point at normal speed, then pause and let the human have
control". You can have many of them; in more complex programs you would need
them at different places. RIGHT click on a line of your source and choose "set
breakpoint".

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).

Now run the program with F5 as usual.


Note that the Debug Control window is opened and that the blue line states that the
line "from math import pi" is ready to be executed (the 7 is for line number 7 in the
source file).

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.

Click the Step button again.


Note that the new variable height has been created and has a value of '14'.

Click the Step button again.


Notice that there is an error in the run of the program at this point (the yellow bar in
the Debug Control window). The interpreter is saying that it cannot multiply
"sequence by non-int of type 'float'". What it means is that the two input variables are
of the wrong type to be combined with numeric types. This has to be corrected before
any more debugging takes place. This is fixed by using the eval function in the two
input statements.

"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

Explanations of a few other things in the Debug Control window

 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).

Figure 7-1: The Debug Control window.


Figure 7-2: Running the Dragon Realm game under the debugger.

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.

The Go and Quit Buttons


If you get tired of clicking the Step button repeatedly and just want the program to run normally, click
the Go button at the top of the Debug Control window. This will tell the program to run normally instead
of stepping.
To terminate the program entirely, just click the Quit button at the top of the Debug Control window. The
program will exit immediately. This is helpful if you must start debugging again from the beginning of
the program.

Stepping Into, Over, and Out


Start the Dragon Realm program with the debugger. Keep stepping until the debugger is at line 38. As
shown in Figure 7-3, this is the line with displayIntro(). When you click Step again, the debugger will jump
into this function call and appear on line 5, the first line in the displayIntro() function. The kind of stepping
you have been doing is called stepping into. This is different from stepping over, explained next.
Figure 7-3: Keep stepping until you reach line 38.

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.

Find the Bug


The debugger can help you find the cause of bugs in your program. As an example, here is a small
program with a bug. The program comes up with a random addition problem for the user to solve. In the
interactive shell window, click on File, then New Window to open a new file editor window. Type this
program into that window, and save the program as buggy.py.
buggy.py
1. import random
2. number1 = random.randint(1, 10)
3. number2 = random.randint(1, 10)
4. print('What is ' + str(number1) + ' + ' + str(number2) + '?')
5. answer = input()
6. if answer == number1 + number2:
7. print('Correct!')
8. else:
9. print('Nope! The answer is ' + str(number1 + number2))

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.)

Figure 7-4: number1 is set to 4 and number2 is set to 8.


5. answer = input()

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.

Example Using Break Points


Here is a program that simulates coin flips by calling random.randint(0, 1). The function returning the
integer 1 will be “heads” and returning the integer 0 will be “tails”. The flips variable will track how many
coin flips have been done. The heads variable will track how many came up heads.
The program will do “coin flips” one thousand times. This would take a person over an hour to do, but the
computer can do it in one second! Type in the following code into the file editor and save it
as coinFlips.py. If you get errors after typing this code in, compare the code you typed to the book’s code
with the online diff tool at http://invpy.com/diff/coinflips.
coinFlips.py
1. import random
2. print('I will flip a coin 1000 times. Guess how many times it will come up heads. (Press enter to begin)')
3. input()
4. flips = 0
5. heads = 0
6. while flips < 1000:
7. if random.randint(0, 1) == 1:
8. heads = heads + 1
9. flips = flips + 1
10.
11. if flips == 900:
12. print('900 flips and there have been ' + str(heads) + ' heads.')
13. if flips == 100:
14. print('At 100 tosses, heads has come up ' + str(heads) + ' times so far.')
15. if flips == 500:
16. print('Half way done, and heads has come up ' + str(heads) + ' times.')
17.
18. print()
19. print('Out of 1000 coin tosses, heads came up ' + str(heads) + ' times!')
20. print('Were you close?')

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.

Figure 7-6: Three break points set.

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.

You might also like