Module 4 Notes
Module 4 Notes
Organising Files:
The shutil (shell utilities) module lets you copy, move, rename, and delete files or entire
directories.
• shutil.copy(source, destination)
Copies the file at source to destination.
If destination is a folder, the file is copied into it.
• shutil.copytree(source_folder, destination_folder)
Recursively copies an entire directory tree.
• shutil.move(source, destination)
Moves a file or folder. Renames if the destination is just a filename.
• shutil.rmtree(path)
Deletes a folder and all its contents.
2. Walking a Directory Tree
Python’s os.walk() function generates the file names in a directory tree by walking the tree
either top-down or bottom-up.
Syntax:
import os
Explanation:
• foldername: Current folder being walked through.
Python’s zipfile module allows you to create, read, write, extract, and list ZIP files.
Goal:
Steps:
Explanation:
• ^(.*?): Matches and captures any characters at the start of the filename.
• The use of re.VERBOSE allows comments and spacing in the regex for readability.
for filename in os.listdir('.'): // Lists every file and folder in the current directory (.).
mo = date_pattern.search(filename)
• mo stands for "match object".
• search() looks for a match of the date pattern in the filename.
• If the pattern is found, mo will contain the matched text and groups.
if mo is None:
continue // If no date is found in the filename, skip to the next file.
shutil.move(filename, euro_filename) // Renames (moves) the file from the original name to the new
name.
example
Project: Backing Up a Folder into a ZIP File
Goal:
Create a ZIP file that contains the entire contents of a folder and ensures previous backups
aren’t overwritten.
Features:
import zipfile, os # Import the modules needed for zipping files and navigating the file system
def backup_to_zip(folder):
# Convert the folder name to an absolute path (for consistency and avoiding confusion)
folder = os.path.abspath(folder)
# Keep incrementing the number until we find a filename that doesn't exist yet
while True:
zip_filename = os.path.basename(folder) + f'_{number}.zip' # e.g., 'myfolder_1.zip'
if not os.path.exists(zip_filename): # Check if this ZIP file already exists
break # If not, we can use this name
number += 1 # Otherwise, try the next number
print(f'Creating {zip_filename}...')
# Walk through every folder, subfolder, and file in the given folder
for foldername, subfolders, filenames in os.walk(folder):
print(f'Adding files in {foldername}...')
# Skip any files that are already backup ZIPs made by this script
if filename.startswith(new_base) and filename.endswith('.zip'):
continue # Don’t back up backup ZIP files
# Create the full path of the file and add it to the ZIP
file_path = os.path.join(foldername, filename)
backup_zip.write(file_path)
1. Raising Exceptions
Purpose:
if width <= 2:
raise Exception('Width must be greater than 2.') # Width
must allow drawing a box
if height <= 2:
raise Exception('Height must be greater than 2.') #
Height too small to make a box
box_print('*', 4, 4)
Output:
markdown
Copy code
****
* *
* *
****
If input is invalid:
box_print('**', 4, 4)
Raises:
Purpose:
To log or display the full traceback message without crashing the program.
Example:
import traceback
try:
raise Exception('This is the error message.')
except:
error_file = open('error_log.txt', 'w')
error_file.write(traceback.format_exc()) # Get the traceback
as a string and write it to a file
error_file.close()
print('The traceback info was written to error_log.txt')
What It Does:
3. Assertions
Purpose:
Example:
pod_bay_door_status = 'open'
Output:
Tip:
Use assertions for sanity checks during development, not for handling runtime user input.
4. Logging
Purpose:
To track and record what the program is doing, especially useful in debugging large programs.
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(f'Start of factorial({n})')
total = 1
for i in range(1, n + 1):
total *= i
logging.debug(f'i = {i}, total = {total}')
logging.debug(f'End of factorial({n})')
return total
print(factorial(5))
logging.debug('End of program')
Output:
(Logged in console)
Logging Levels:
5. IDLE’s Debugger
Purpose:
To step through your code line by line and watch variables change.
How to Use:
Example:
total = x + y
return total
result = add(5, 7)
print(result)