JSTAcademy
0 XP
Dashboard
Crash Courses
Modules, Error Handling & File I/O
16 min
Masters+180 XP
Crash Courses · Masters

Modules, Error Handling & File I/O

Import modules, handle exceptions cleanly, and read/write files with pathlib.
16 min read+180 XP on completionCert: Python Crash Course
Tap any word in the text below to start reading from there.

Modules, Error Handling & File I/O

Importing Modules

# Import the whole module — access with module.function()
import math
import random
import json
from datetime import datetime

print(math.pi)                    # 3.141592...
print(math.sqrt(144))             # 12.0
print(random.randint(1, 100))     # random int between 1 and 100
print(datetime.now())             # 2026-10-03 14:35:00.123456

# Import specific names — use without prefix
from math import pi, sqrt, ceil, floor
from pathlib import Path
from collections import defaultdict, Counter

print(pi)          # 3.141592...
print(ceil(4.1))   # 5

---

try / except / else / finally

# Basic try/except
def divide(a, b):
    try:
        result = a / b
    except ZeroDivisionError:
        print("Error: Cannot divide by zero")
        return None
    else:
        # Runs only if no exception occurred
        print(f"Result: {result}")
        return result
    finally:
        # Runs always — exception or not
        print("divide() called")

divide(10, 2)   # Result: 5.0 / divide() called
divide(10, 0)   # Error: ... / divide() called

# Catching multiple exception types
def parse_int(value):
    try:
        return int(value)
    except (ValueError, TypeError) as e:
        print(f"Parse failed: {e}")
        return None

# Catch any exception (use sparingly)
try:
    risky_operation()
except Exception as e:
    print(f"Unexpected error: {type(e).__name__}: {e}")
    raise   # re-raise after logging — don't silently swallow errors

---

Raising Exceptions

def get_percentage(value, total):
    """Calculate percentage. Validates inputs before calculating."""
    if not isinstance(value, (int, float)):
        raise TypeError(f"value must be numeric, got {type(value).__name__}")
    if total == 0:
        raise ValueError("total cannot be zero")
    if value < 0 or total < 0:
        raise ValueError("value and total must be non-negative")
    return (value / total) * 100

try:
    print(get_percentage(75, 100))    # 75.0
    print(get_percentage(75, 0))      # raises ValueError
except ValueError as e:
    print(f"ValueError: {e}")

---

Custom Exception Classes

class ValidationError(Exception):
    """Raised when input data fails validation."""
    def __init__(self, field, message):
        self.field = field
        super().__init__(f"[{field}] {message}")

class AuthenticationError(Exception):
    """Raised when authentication fails."""
    pass

def validate_email(email):
    if "@" not in email:
        raise ValidationError("email", f"'{email}' is not a valid email address")
    if len(email) > 254:
        raise ValidationError("email", "Email exceeds maximum length")
    return True

try:
    validate_email("not-an-email")
except ValidationError as e:
    print(f"Validation failed on field '{e.field}': {e}")

---

File I/O with pathlib

from pathlib import Path

# Writing a file
data_dir = Path("data")
data_dir.mkdir(exist_ok=True)   # create directory, no error if exists

output = data_dir / "report.txt"   # / operator builds paths safely
output.write_text("Line 1\nLine 2\nLine 3", encoding="utf-8")

# Reading a file
content = output.read_text(encoding="utf-8")
print(content)

lines = content.splitlines()   # split into list of lines
print(lines)                   # ['Line 1', 'Line 2', 'Line 3']

# Check existence
print(output.exists())         # True
print(output.name)             # report.txt
print(output.stem)             # report
print(output.suffix)           # .txt
print(output.parent)           # data

# List files in a directory
for f in data_dir.iterdir():
    print(f.name)

---

Parsing CSV-Style Data with Error Handling

from pathlib import Path

CSV_DATA = """name,age,score
Jordan,28,94.5
Tony,34,88.0
invalid_row
Aria,25,97.2
,30,70.0
"""

def parse_csv(csv_string):
    """
    Parse a CSV string into a list of dicts.
    Skips malformed rows and logs warnings.
    """
    lines = csv_string.strip().splitlines()
    headers = lines[0].split(",")
    records = []

    for line_num, line in enumerate(lines[1:], start=2):
        parts = line.split(",")
        if len(parts) != len(headers):
            print(f"  Warning: Line {line_num} has wrong field count, skipping")
            continue
        row = dict(zip(headers, parts))
        if not row.get("name"):
            print(f"  Warning: Line {line_num} missing name, skipping")
            continue
        try:
            row["age"] = int(row["age"])
            row["score"] = float(row["score"])
        except ValueError as e:
            print(f"  Warning: Line {line_num} type conversion failed ({e}), skipping")
            continue
        records.append(row)

    return records

records = parse_csv(CSV_DATA)
for r in records:
    print(r)
0%