BPLCK205B M4 1
BPLCK205B M4 1
BPLCK205B
Module 4-Notes
➢ The first shutil.copy() call copies the file at C:\spam.txt to the folder C:\delicious. The return
value is the path of the newly copied file. Note that since a folder was specified as the
destination
➢ The original spam.txt filename is used for the new, copied file’s filename. The second
shutil.copy()call also copies the file at C:\eggs.txt to the folder C:\delicious but gives the
copied file the name eggs2.txt.
Program:
➢ 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
➢ Both of the previous examples worked under the assumption that there was a folder eggs in
the C:\ directory. But if there is no eggs folder, then move() will rename bacon.txt to a file
named eggs.
➢ You can 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, you 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.
➢ If you had any important files ending with .rxt, they would have been accidentally,
permanently deleted
➢ Since Python’s built-in shutil.rmtree() function irreversibly deletes files and folders, it can be
dangerous to use
➢ A much better way to delete files and folders is with the third-party send2trash module
➢ You can install this module by running pip install send2trash from a Terminal window
➢ 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.
>>> import send2trash
>>> baconFile = open('bacon.txt', 'a') # creates the file
>>> baconFile.write('Bacon is not a vegetable.')
25
>>> baconFile.close()
>>> send2trash.send2trash('bacon.txt')
Figure: An example folder that contains three folders and four files
➢ To read the contents of a ZIP file, first you must create a ZipFile object (note the capital letters
Z and F).
➢ ZipFile objects are conceptually similar to the File objects you saw returned by the open()
function
➢ They are values through which the program interacts with the file. To create a ZipFile object,
call the zipfile.ZipFile() function
For example
>>> import zipfile, os
>>> os.chdir('C:\\') # move to the folder with example.zip
>>> exampleZip = zipfile.ZipFile('example.zip')
>>> exampleZip.namelist()
['spam.txt', 'cats/', 'cats/catnames.txt', 'cats/zophie.jpg']
>>> spamInfo = exampleZip.getinfo('spam.txt')
>>> spamInfo.file_size
13908
>>> spamInfo.compress_size
3828
>>> 'Compressed file is %sx smaller!' % (round(spamInfo.file_size / spamInfo
.compress_size, 2))
'Compressed file is 3.63x smaller!'
>>> exampleZip.close()
➢ A ZipFile object has a namelist() method that returns a list of strings for all the files and folders
contained in the ZIP file.
➢ These strings can be passed to the getinfo() 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.
➢ The extract() method for ZipFile objects will extract a single file from the ZIP file.
Continue the interactive shell example
>>> exampleZip.extract('spam.txt')
'C:\\spam.txt'
>>> exampleZip.extract('spam.txt',
'C:\\some\\new\\folders')
'C:\\some\\new\\folders\\spam.txt'
>>> exampleZip.close()
3.3 Creating and Adding to ZIP Files
➢ To create your own compressed ZIP files, you must open the ZipFile object in write mode by
passing 'w' as the second argument.
➢ When you pass a path to the write() method of a ZipFile object, Python will compress the file
at that path and add it into the ZIP file.
➢ The write() method’s first argument is a string of the filename to add.
➢ The second argument is the compression type parameter, which tells the computer what
algorithm it should use to compress the files;
>>> import zipfile
>>> newZip = zipfile.ZipFile('new.zip', 'w')
>>> newZip.write('spam.txt',
compress_type=zipfile.ZIP_DEFLATED) >>>
newZip.close()
#! python3
# renameDates.py - Renames filenames with American MM-DD-YYYY date
format
# to European DD-MM-YYYY.
import shutil, os, re
# Create a regex that matches files with the American date format.
datePattern = re.compile(r"""^(.*?) # all text before the date ((0|1)?\d)-
# one or two digits for the month
((0|1|2|3)?\d)- # one or two digits for the day
((19|20)\d\d) # four digits for the year
(.*?)$ # all text after the date
""", re.VERBOSE)
➢ After importing the re module at the top, call re.compile() to create a Regex object
➢ Passing re.VERBOSE for the second argument w will allow whitespace and comments
in the regex string to make it more readable.
➢ Next, the program will have to loop over the list of filename strings returned from os.listdir()
and match them against the regex.
#! python3
# renameDates.py - Renames filenames with American MM-DD-YYYY date format
# to European DD-MM-YYYY.
--snip—
➢ To keep the group numbers straight, try reading the regex from the beginning and count up
each time you encounter an opening parenthesis.
➢ Without thinking about the code, just write an outline of the regular expression.
➢ As the final step, concatenate the strings in the variables made in the previous step with the
European-style date:
#! python3
# renameDates.py - Renames filenames with American MM-DD-YYYY date format
# to European DD-MM-YYYY.
--snip--
# Form the European-style filename.
euroFilename = beforePart + dayPart + '-' + monthPart + '-' + yearPart +
afterPart # Get the full, absolute file paths. absWorkingDir = os.path.abspath('.')
amerFilename = os.path.join(absWorkingDir, amerFilename) euroFilename =
os.path.join(absWorkingDir, euroFilename)
➢ The code for this program will be placed into a function named backupToZip(). This will
make it easy to copy and paste the function into other Python programs that need this
functionality.
#! python3
# backupToZip.py - Copies an entire folder and its contents into # a
ZIP file whose filename increments.
➢ Add the shebang (#!) line, describe what the program does, and import the zipfile and os
modules
➢ Define a backupToZip() function that takes just one parameter, folder. This parameter is a
string path to the folder whose contents should be backed up.
➢ The function will determine what filename to use for the ZIP file it will create; then the
function will create the file, walk the folder folder, and each of the subfolders and files to the
ZIP file.
#! python3
# backupToZip.py - Copies an entire folder and its contents into # a ZIP
file whose filename increments.
--snip-- while
True:
zipFilename = os.path.basename(folder) + '_' + str(number) + '.zip' if not
os.path.exists(zipFilename):
break
number = number + 1 # Create the ZIP
file. print('Creating %s...' % (zipFilename))
backupZip = zipfile.ZipFile(zipFilename, 'w')
# TODO: Walk the entire folder tree and compress the files in each folder. print('Done.')
backupToZip('C:\\delicious')
Step 3: Walk the Directory Tree and Add to the ZIP File
➢ Now you need to use the os.walk() function to do the work of listing every file in the folder and
its subfolders
#! python3
# backupToZip.py - Copies an entire folder and its contents into # a
ZIP file whose filename increments.
--snip—
# Walk the entire folder tree and compress the files in each folder.
for foldername, subfolders, filenames in os.walk(folder):
print('Adding files in %s...' % (foldername)) #
Add the current folder to the ZIP file.
backupZip.write(foldername)
# Add all the files in this folder to the ZIP file.
for filename in filenames:
newBase / os.path.basename(folder) + '_' if
filename.startswith(newBase) and filename.endswith('.zip')
continue # don't backup the backup ZIP
files
backupZip.write(os.path.join(foldername, filename))
backupZip.close() print('Done.')
backupToZip('C:\\delicious')
Creating delicious_1.zip...
Adding files in C:\delicious...
Adding files in C:\delicious\cats...
Adding files in C:\delicious\waffles...
Adding files in C:\delicious\walnut...
Adding files in C:\delicious\walnut\waffles...
Done.
CHAPTER -2 DEBUGGING
1. Raising Exceptions
➢ 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 ➢ For example
➢ If there are no try and except statements covering the raise statement that raised the exception,
the program simply crashes and displays the exception’s error message..
for sym, w, h in (('*', 4, 4), ('O', 20, 5), ('x', 1, 3), ('ZZ', 3, 3)):
try:
boxPrint(sym, w, h) except Exception as err: print('An
exception happened: ' + str(err))
➢ This program uses the except Exception as err form of the except statement If an Exception
object is returned from boxPrint()
➢ This except statement will store it in a variable named err. The Exception object can then be
converted to a string by passing it to str() to produce a userfriendly error message
Output
****
**
**
****
OOOOOOOOOOOOOOOOOOOO
O O
O O
O O
OOOOOOOOOOOOOOOOOOOO
An exception happened: Width must be greater than 2. An
exception happened: Symbol must be a single character
string.
def spam():
bacon()
def bacon(): raise Exception('This is the
error message.') spam()
Output:
➢ The 116 is the return value from the write() method, since 116 characters were written to the
file.
➢ set podBayDoorStatus to 'open', so from now on, we fully expect the value of this variable to
be 'open'
➢ In a program that uses this variable, we might have written a lot of code under the assumption
that the value is 'open'—code that depends on its being 'open' in order to work as we expect.
So we add an assertion to make sure we’re right to assume podBayDoorStatus is 'open'
➢ Here, we include the message 'The pod bay doors need to be "open".' so it’ll be easy to see
what’s wrong if the assertion fails.
➢ while writing switchLights() you had added an assertion to check that at least one of the lights
is always red,
➢ include the following at the bottom of the function:
4. Logging
➢ Logging is a great way to understand what’s happening in your program and in what
order its happening.
➢ 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. Using the logging Module
➢ To enable the logging module to display log messages on your screen as your
program runs,
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
Program:
➢ 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().
Output:
Output
Disabling Logging
➢ The logging.disable() function disables these so that you don’t have to go into your program
and remove all the logging calls by hand.
➢ pass logging.disable() a logging level, and it will suppress all log messages at that level or
lower
➢ Since logging.disable() will disable all messages after it, you will probably want to add it near
the import logging line of code in your program
Logging to a File
➢ Instead of displaying the log messages to the screen, you can write them to a text file. The
logging.basicConfig() function takes a filename keyword argument,
import logging
logging.basicConfig(filename='myProgramLog.txt',level=logging.DEBUG,
format=' %(asctime)s - %(levelname)s - %(message)s')
5. IDLE ’s Debugger
➢ The debugger is a feature of IDLE that allows you to execute your program one line at a time.
➢ The debugger will run a single line of code and then wait for you to tell it to continue
➢ To enable IDLE’s debugger, click Debug4Debugger in the interactive shell window.
➢ When the Debug Control window appears, select all four of the Stack, Locals, Source, and
Globals checkboxes so that the window shows the full set of debug information
➢ While the Debug Control window is displayed, any time you run a program from the file
editor
➢ debugger will pause execution before the first instruction and display the following:
➢ The line of code that is about to be executed
➢ A list of all local variables and their values
➢ A list of all global variables and their values
Figure: The Debug Control window
➢ You’ll notice that in the list of global variables there are several variables you haven’t defined,
such as __builtins__, __doc__, __file__, and so on. These are variables that Python
automatically sets whenever it runs a program.
➢ The program will stay paused until you press one of the five buttons in the Debug Control
window: Go, Step, Over, Out, or Quit.
Go
➢ Clicking the Go button will cause the program to execute normally until it terminates or
reaches a breakpoint
➢ If you are done debugging and want the program to continue normally, click the Go button.
Step
➢ Clicking the Step button will cause the debugger to execute the next line of code and then
pause again
➢ The Debug Control window’s list of global and local variables will be updated if their values
change.
➢ If the next line of code is a function call, the debugger will “step into” that function and jump
to the first line of code of that function.
Over
➢ Clicking the Over button will execute the next line of code, similar to the Step button.
➢ The Over button will “step over” the code in the function. The function’s code will be
executed at full speed, and the debugger will pause as soon as the function call returns.
➢ For example, if the next line of code is a print() call, you don’t really care about code inside
the built-in print() function; you just want the string you pass it printed to the screen.
Quit
➢ If you want to stop debugging entirely and not bother to continue executing the rest of the
program, click the Quit button
➢ The Quit button will immediately terminate the program. If you want to run your program
normally again, select Debug4Debugger again to disable the debugger.
➢ The program hasn’t crashed, but the sum is obviously wrong. Let’s enable the Debug Control
window and run it again, this time under the debugger
➢ When you press F5 or select Run4Run Module (with Debug4Debugger enabled and all four
checkboxes on the Debug Control window checked), the program starts in a paused state on
line 1.
➢ The debugger will always pause on the line of code it is about to execute.
Figure The Debug Control window when the program first starts under the debugger
➢ Click the Over button once to execute the first print() call. You should use Over instead of
Step here, since you don’t want to step into the code for the print() function.
➢ The Debug Control window will update to line 2, and line 2 in the file editor window will be
highlighted.
Figure: The Debug Control window after clicking Over
➢ Click Over again to execute the input() function call, and the buttons in the Debug Control
window will disable themselves while IDLE waits for you to type something for the input()
call into the interactive shell window.
➢ Enter 5 and press Return. The Debug Control window buttons will be reenabled.
➢ Keep clicking Over, entering 3 and 42 as the next two numbers, until the debugger is on line
7, the final print() call in the program
➢ Globals section that the first, second, and third variables are set to string values '5', '3', and '42'
instead of integer values 5, 3, and 42.
➢ When the last line is executed, these strings are concatenated instead of added together, causing
the bug.
Figure The Debug Control window on the last line. The variables are set to strings, causing the bug.
Breakpoints
➢ A breakpoint can be set on a specific line of code and forces the debugger to mpause whenever
the program execution reaches that line.
➢ Open a new file editor window and enter the following program, which simulates flipping a coin 1,000
times.
➢ The random.randint(0, 1) call u will return 0 half of the time and 1 the other half of the time.
➢ This can be used to simulate a 50/50 coin flip where 1 represents heads.
Output:
Halfway done!
Heads came up 490 times.
➢ If you ran this program under the debugger, you would have to click the Over button thousands
of times before the program terminated.
➢ If you were interested in the value of heads at the halfway point of the program’s execution,
when 500 of 1000 coin flips have been completed, you could instead just set a breakpoint on
the line print('Halfway done!')
➢ To set a breakpoint, right-click the line in the file editor and select Set Breakpoint,
Figure : Setting a breakpoint