Introduction to Python Programming (BPLCK105B/205B)                                Module 4
MODULE 4
Organizing Files: The shutil Module, Walking a Directory Tree, Compressing Files
with the zipfile Module, Project: Renaming Files with American-Style Dates to
European-Style Dates, Project: Backing Up a Folder into a ZIP File, Debugging:
Debugger.
Textbook 1: Chapters 10, 11
CHAPTER 1: ORGANIZING FILES
   With macOS and Linux, file browser most likely shows extensions automatically.
   With Windows, file extensions may be hidden by default.
   To show extensions, go to Start Control Panel Appearance and Personalization Folder
   Options.
   On the View tab, under Advanced Settings, uncheck the Hide extensions for known file
   types checkbox.
1.1 The shutil Module
   The shutil (or shell utilities) module has functions to copy, move, rename, and delete files
   in Python programs.
   To use the shutil functions, first we need to use import shutil.
Copying Files and Folders
   The shutil module provides functions for copying files, as well as entire folders.
   Calling shutil.copy(source, destination) will copy the file at the path source to the folder
   at the path destination. (Both 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.
   This function returns a string of the path or Path object of the copied file.
Example:        >>> import shutil, os
                >>> from pathlib import Path
                >>> p = Path.home()
                >>> shutil.copy(p / 'spam.txt', p / 'some_folder')
                'C:\\Users\\Al\\some_folder\\spam.txt'
                >>>shutil.copy(p / 'eggs.txt', p / 'some_folder/eggs2.txt')
                WindowsPath('C:/Users/Al/some_folder/eggs2.txt')
CSE, CITECH                                  2022-23                                       Page 1
Introduction to Python Programming (BPLCK105B/205B)                                 Module 4
   The first shutil.copy() call copies the file at C:\Users\sonia\spam.txt to the folder
   C:\Users\sonia\some_folder. The return value is the path of the newly copied file.
   The second shutil.copy() call also copies the file at C:\Users\sonia\eggs.txt to the folder
   C:\Users\sonia\some_folder but gives the copied file the name eggs2.txt.
   While shutil.copy() will copy a single file, 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.
Example:
 >>> import shutil, os
 >>> from pathlib import Path
 >>> p = Path.home()
 >>> shutil.copytree(p / 'spam', p / 'spam_backup')
 WindowsPath('C:/Users/Al/spam_backup')
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.
Example:          >>>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() calls
   says,             \bacon.txt into the folder C:\eggs
   in C:\eggs, it would have been overwr                   s easy to overwrite files. The destination
   path can also specify a filename.
Example:                             >>>shutil.move('C:\\bacon.txt','C:\\eggs\\new_bacon.txt')
                                     'C:\\eggs\\new_bacon.txt'
This line says,            C:\bacon.txt into the folder C:\eggs, rename that bacon.txt file to
CSE, CITECH                                   2022-23                                        Page 2
Introduction to Python Programming (BPLCK105B/205B)                                    Module 4
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.
         >>> shutil.move('C:\\bacon.txt', 'C:\\eggs')
         'C:\\eggs'
Here, move()         t find a folder named eggs in the C:\ directory and so assumes that destination
must be specifying a filename, not a folder. So the bacon.txt text file is renamed to eggs.
Finally, the folders that make up the destination must already exist, or else Python will throw
an exception.
Example:          >>> 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'
Python looks for eggs and ham inside the directory does_not_exist. It                          t find the
nonexistent directory, so it          t move spam.txt to the path we specified.
Permanently Deleting Files and Folders
Deleting a single file or a single empty folder with functions in the os module, whereas to
delete a folder and all of its contents, can use the shutil module.
        o Calling os.unlink(path) will delete the file at path.
        o Calling os.rmdir(path) will delete the folder at path. This folder must be empty of
              any files or folders.
        o Calling shutil.rmtree(path) will remove the folder at path, and all files and folders it
              contains will also be deleted.      import os
                                                  from pathlib import Path
Example:                                          for filename in Path.home().glob('*.txt'):
                                                           #os.unlink(filename)
                                                           print(filename)
Any important files ending with .txt, they would have been accidentally, permanently deleted.
Instead, first run the program: with the os.unlink() call is commented, so Python ignores it.
CSE, CITECH                                      2022-23                                          Page 3
Introduction to Python Programming (BPLCK105B/205B)                                Module 4
Instead, print the filename of the file that would have been deleted.
Once we are certain the program works as intended, delete the print(filename) line and
uncomment the os.unlink(filename) line. Then run the program again to actually delete the files.
Safe Deletes with the send2trash Module
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.
Using send2                                      s regular delete functions, because it will send
folders and files to                s trash or recycle bin instead of permanently deleting them.
If a bug in our program deletes som                                     t intend to delete, we can
later restore it from the recycle bin.
Example:
 >>> import send2trash
 >>> baconFile=open('bacon.txt','a')
 >>> baconFile.write('bacon is not a vegetable.')
 25
 >>> baconFile.close()
 >>> baconFile=open('bacon.txt','r')
 >>> baconFile.read()
 'bacon is not a vegetable.'
 >>> baconFile.close()
 >>> send2trash.send2trash('bacon.txt')
 >>> baconFile=open('bacon.txt','r')
 Traceback (most recent call last):
 FileNotFoundError: [Errno 2] No such file or directory: 'bacon.txt'
1.2 Walking a Directory Tree
To rename every file in some folder and also every file in every subfolder of that folder. That
is, to navigate through the directory tree, touching each file in the path. Python provides a
function to handle this process.
      s look at the C:\delicious folder with its contents, shown in Figure
CSE, CITECH                                   2022-23                                      Page 4
Introduction to Python Programming (BPLCK105B/205B)                               Module 4
        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(' ')
The os.walk() function is passed a single string value: the path of a folder. os.walk() function
is used in a for loop statement to walk a directory tree, much like how we can use the range()
function to walk over a range of numbers. Unlike range(), the os.walk() function will return
three values on each iteration through the loop:
 1. A string of the current          name
 2. A list of strings of the folders in the current folder
 3. A list of strings of the files in the current folder (By current folder, we mean the folder for
    the current iteration of the for loop. The current working directory of the program is not
    changed by os.walk().)
CSE, CITECH                                   2022-23                                     Page 5
Introduction to Python Programming (BPLCK105B/205B)                                 Module 4
Since , it returns three values hence make use of three variables with the names foldername,
subfolders, and filenames.
Output:
              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.
Since os.walk() returns lists of strings for the subfolder and filename variables, we can use these
lists in their own for loops.
Compressing Files with the zipfile Module
ZIP files (with the .zip file extension), which can hold the compressed contents of many other
files.
Compressing a file reduces its size, which is useful when transferring it over the Internet. And
since a ZIP file can also contain mu                                   s a handy way to package
several files into one. This single file, called an archive file, can then be, attached to an email.
Python programs can both create and open (or extract) ZIP files using functions in the zipfile
module. Say we have a ZIP file named example.zip that has the contents shown in Figure.
CSE, CITECH                                        2022-23                                   Page 6
Introduction to Python Programming (BPLCK105B/205B)                                   Module 4
Reading ZIP Files
    To read the contents of a ZIP file, first create a ZipFile object (note the capital letters Z
    and F).
    ZipFile objects are conceptually similar to the File objects. They are values through which
    the program interacts with the file.
    To create a ZipFile object, call the zipfile.ZipFile() function, passing it a string of the .zip
        s filename.
    zipfile is the name of the Python module and ZipFile() is the name of the function.
Example
>>> import zipfile, os
>>> from pathlib import Path
>>> p = Path.home()
>>> exampleZip = zipfile.ZipFile(p / '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
>>> 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.
    While a ZipFile object represents an entire archive file, a ZipInfo object holds useful
    information about a single file in the archive.
CSE, CITECH                                  2022-23                                         Page 7
Introduction to Python Programming (BPLCK105B/205B)                                Module 4
Extracting from ZIP Files
The extractall() method for ZipFile objects extracts all the files and folders from a ZIP file
into the current working directory.
Example:
 >>> 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 current working
directory. Optionally, 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, replaced the call with exampleZip.extractall('C:\\
delicious'), the code would extract the files from example.zip into a newly created C:\delicious
folder. The extract() method for ZipFile objects will extract a single file from the ZIP file.
Example:
                   >>> exampleZip.extract('spam.txt')
                   'C:\\spam.txt'
                   >>> exampleZip.extract('spam.txt', 'C:\\some\\new\\folders')
                   'C:\\some\\new\\folders\\spam.txt'
                   >>> exampleZip.close()
The string pass to extract() must match one of the strings in the list returned by namelist().
Optionally, can pass a second argument to extract() to extract the file into a folder other than
the current working directory. If this second argument is a folder that doesn t yet exist, Python
will create the folder. The value that extract() returns is the absolute path to which the file was
extracted.
Creating and Adding to ZIP Files
To create compressed ZIP files, must open the ZipFile object in write mode by passing 'w' as
the second argument.
CSE, CITECH                                  2022-23                                        Page 8
Introduction to Python Programming (BPLCK105B/205B)                                  Module 4
By passing a path to the write() method of a ZipFile object, Python will compress the file at
that path and add it into t                                     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.
We can always just set this value to zipfile.ZIP_DEFLATED. (This specifies the deflate
compression algorithm, which works well on all types of data.)
Example:
  >>> import zipfile
  >>> newZip = zipfile.ZipFile('new.zip', 'w')
  >>> newZip.write('spam.txt', compress_type=zipfile.ZIP_DEFLATED)
  >>> newZip.close()
This code will create a new ZIP file named new.zip that has the compressed contents of
spam.txt. Writing to files in write mode will erase all existing contents of a ZIP file. To add files
to an existing ZIP file, pass 'a' as the second argument to zipfile.ZipFile() to open the ZIP file
in append mode.
CHAPTER 2: DEBUGGING
Our computer will do only what we tell it to do;                                               we
intended it to do. Even professional prog
program has a problem.
going wrong.
2.1 Raising Exceptions
    Python raises an exception whenever it tries to execute invalid code.
    We have already
    statements so that our program can recover from exceptions that we anticipated.
    But we can also raise our own exceptions in our code.
                                                                                               ve
    the program execution to the
    Exceptions are raised with a raise statement.
CSE, CITECH                                   2022-23                                         Page 9