Programming with PythonUnit 68 min read

File Handling, Exceptions & Error Management in Python

Unit 6 of Programming with Python covers reading/writing files (text/binary), exception handling (try-except), and debugging techniques—essential for building robust programs that interact with external data or handle runtime errors gracefully.

TAKEAWAYS:

  • File handling lets programs read/write data persistently (e.g., saving user profiles, logging errors, or processing CSV reports).
  • Exceptions are runtime errors (e.g., FileNotFoundError, ValueError) that disrupt normal flow unless caught with try-except.
  • Python’s with statement auto-closes files and ensures resources are released, even if errors occur.
  • Common file modes ('r', 'w', 'a', 'b') control how files are opened (read, write, append, binary).
  • Logical errors (e.g., incorrect calculations) aren’t exceptions—they require debugging (e.g., assert statements).
  • Real-world apps (e.g., Khalti’s transaction logs, Ncell’s customer data) rely on file handling for data storage and recovery.

1. File Handling in Python

Files store data permanently on disk. Python provides built-in functions to interact with them via file objects.

Key Concepts

  • File Modes: Table of common modes and their purposes:

    Mode Description Example Use Case
    'r' Read (default) Opening a text file for input
    'w' Write (overwrites existing file) Creating a new log file
    'a' Append (adds to existing file) Adding new records to a database
    'r+' Read + Write Updating a configuration file
    'b' Binary mode (e.g., images, PDFs) Reading a .jpg file
  • File Methods:

    file = open("data.txt", "r")  # Open file
    content = file.read()         # Read entire content
    lines = file.readlines()       # Read as list of lines
    file.write("New data")        # Write data
    file.close()                  # Close file (critical!)
    

Example: Reading a CSV File (Like NEPSE Stock Data)

Assume nepse_stocks.csv contains:

Symbol,Price,Change
NBL,1200,+50
HBANK,850,-20
with open("nepse_stocks.csv", "r") as file:
    for line in file:
        symbol, price, change = line.strip().split(",")
        print(f"{symbol} changed by {change}")

Output:

NBL changed by +50
HBANK changed by -20

Why with? The with statement automatically closes the file when the block ends, even if an error occurs. Without it, you’d need file.close() manually.

Binary Files (e.g., Images, Executables)

with open("profile.jpg", "rb") as img_file:  # 'rb' = read binary
    binary_data = img_file.read()

Use Case: Apps like Pathao might store driver location data in binary format for efficiency.


2. Exceptions and Error Handling

Exceptions are runtime errors that disrupt program flow. Python uses try-except blocks to handle them gracefully.

Common Exceptions

Exception Cause Example
FileNotFoundError File doesn’t exist open("missing.txt", "r")
ValueError Invalid data type (e.g., int("abc")) age = int(input("Enter age: "))
ZeroDivisionError Division by zero x = 10 / 0
KeyError Dictionary key missing data["nonexistent"]
TypeError Invalid operation (e.g., 5 + "a") result = 5 + "hello"

Example: Handling a Missing File (Like Daraz’s Order Logs)

try:
    with open("orders.log", "r") as file:
        orders = file.read()
except FileNotFoundError:
    print("Error: Order log file not found. Creating a new one...")
    with open("orders.log", "w") as file:
        file.write("No orders yet.")

Output if file missing:

Error: Order log file not found. Creating a new one...

Multiple Exceptions

try:
    num = int(input("Enter a number: "))
    result = 10 / num
except ValueError:
    print("Error: Please enter a valid number.")
except ZeroDivisionError:
    print("Error: Cannot divide by zero!")

Raising Exceptions (raise)

Force an exception if a condition isn’t met:

def validate_age(age):
    if age < 18:
        raise ValueError("Age must be 18+")
    return age

3. Debugging Techniques

Not all errors are exceptions. Logical errors (e.g., incorrect calculations) require debugging tools.

Tools

  1. assert Statements:

    def calculate_discount(price, discount):
        assert 0 <= discount <= 1, "Discount must be between 0 and 1"
        return price * (1 - discount)
    

    Use Case: Khalti’s payment system might use assert to validate transaction amounts.

  2. Logging (logging Module):

    import logging
    logging.basicConfig(filename="app.log", level=logging.ERROR)
    try:
        risky_operation()
    except Exception as e:
        logging.error(f"Failed: {e}")
    

    Output in app.log:

    ERROR:Failed: Division by zero
    
  3. Debugging with pdb:

    import pdb; pdb.set_trace()  # Pauses execution here
    x = 10 / 0
    

    Use Case: Debugging NTC’s network traffic scripts to find bottlenecks.


In the Real World

  1. Khalti’s Transaction Logs

    • Idea Used: File handling ('a' mode) to append new transactions to transactions.log.
    • How: Each payment is written as a new line:
      2024-05-20,15:30,USER123,5000,SUCCESS
      
    • Why: Persistent storage for auditing and recovery.
  2. Ncell’s Customer Data Backup

    • Idea Used: Binary file handling ('wb') to store encrypted customer data (users.dat).
    • How: Serialized data (e.g., pickle) is written in binary for efficiency.
    • Why: Faster access than text files and secure against tampering.
  3. Daraz’s Order Queue System

    • Idea Used: Exception handling for failed order processing.
    • How:
      try:
          process_order(order_id)
      except InventoryError:
          notify_seller(order_id)
      
    • Why: Ensures orders aren’t lost if stock is unavailable.

Visual: File Handling Workflow

flowchart TD
    A["Open File\n(`open()`)"] --> B["Read/Write Data\n(`read()`, `write()`)"]
    B --> C["Close File\n(`close()` or `with`)"]
    C --> D["Data Persists\n(on disk)"]
    D -->|"Error"| E["Exception\n(`FileNotFoundError`)"]
    E --> F["Handle Gracefully\n(`try-except`)"]

Visual: Exception Handling Flow

flowchart TD
    A["Try Block\n(Risky Code)"] --> B["Error Occurs?"]
    B -->|"Yes"| C["Except Block\n(Handle Error)"]
    B -->|"No"| D["Continue\n(Success)"]
    C --> E["Log Error\n(Optional)"]
    E --> D

Visual: Binary vs. Text Files

pie
    title File Types in Python
    "Text Files" : 60
    "Binary Files" : 40

Text Files:

  • Human-readable (e.g., .txt, .csv).
  • Use str encoding (e.g., UTF-8). Binary Files:
  • Machine-readable (e.g., .jpg, .exe).
  • Use bytes (e.g., b'\x89PNG\r\n\x1a\n').

Exam Tip

  1. File Modes: Always specify the correct mode (e.g., 'r+' for read-write). Mixing modes (e.g., 'w' on a non-existent file) creates a new file.
  2. with vs. close(): Prefer with—it’s safer and cleaner. Examiners may test your understanding of resource management.
  3. Exception Hierarchy: Know that Exception is the base class. Catch specific exceptions first (e.g., ValueError before Exception).
  4. Logging: Use logging for production code, not print(). Exams may ask to differentiate between debugging (print) and logging.
  5. Binary Files: Remember 'b' mode for non-text files. A common mistake is omitting it for images.
  6. Practical Scenarios: Be ready to write code for:
    • Reading a CSV (like NEPSE stock data).
    • Handling missing files (like Pathao’s driver logs).
    • Validating user input (e.g., Khalti’s transaction amounts).

Key Formula to Remember: For file sizes, use os.path.getsize("file.txt") to check if a file exists before reading:

import os
if os.path.exists("data.txt"):
    with open("data.txt", "r") as file:
        print(file.read())
else:
    print("File not found!")

Based on the TU BITM syllabus for Programming with Python (IT243), unit 6.

Discussion

Loading…