Skip to content

Exception Handling

try-except Statements

Python Exception Handling

Basic Exception Handling

python
# Python - Basic exception handling
def divide_numbers(a, b):
    try:
        result = a / b
        return result
    except ZeroDivisionError:
        print("Error: Divisor cannot be zero")
        return None
    except TypeError:
        print("Error: Incorrect parameter type")
        return None

# Test exception handling
print(divide_numbers(10, 2))   # 5.0
print(divide_numbers(10, 0))   # Error: Divisor cannot be zero
print(divide_numbers("10", 2)) # Error: Incorrect parameter type

# Multiple exception types
def process_data(data):
    try:
        if isinstance(data, str):
            return int(data)
        elif isinstance(data, (int, float)):
            return data
        else:
            raise ValueError("Unsupported data type")
    except (ValueError, TypeError) as e:
        print(f"Data processing error: {e}")
        return None

# Test multiple exceptions
print(process_data("123"))     # 123
print(process_data(456))       # 456
print(process_data("abc"))     # Data processing error: invalid literal for int() with base 10: 'abc'
print(process_data([1, 2, 3])) # Data processing error: Unsupported data type

Complete Exception Handling Structure

python
# Python - Complete exception handling structure
def file_operations(filename):
    try:
        # Try to open the file
        with open(filename, 'r', encoding='utf-8') as f:
            content = f.read()
            print("File read successfully")
            return content
    except FileNotFoundError:
        print(f"File {filename} not found")
        return None
    except PermissionError:
        print(f"No permission to read file {filename}")
        return None
    except UnicodeDecodeError:
        print(f"File {filename} encoding error")
        return None
    except Exception as e:
        print(f"Unknown error: {e}")
        return None
    else:
        # Executed only if no exception occurs
        print("File operation completed")
    finally:
        # Always executed, whether an exception occurred or not
        print("Cleaning up resources")

# Test file operations
file_operations("nonexistent.txt")
file_operations("example.txt")

Exception Chaining and Re-throwing

python
# Python - Exception chaining and re-throwing
def low_level_function():
    try:
        result = 10 / 0
    except ZeroDivisionError as e:
        raise RuntimeError("Low-level function failed") from e

def high_level_function():
    try:
        low_level_function()
    except RuntimeError as e:
        print(f"High-level function caught an error: {e}")
        print(f"Original error: {e.__cause__}")

# Test exception chaining
high_level_function()

# Re-throwing an exception
def process_user_input(user_input):
    try:
        age = int(user_input)
        if age < 0 or age > 150:
            raise ValueError("Age must be between 0-150")
        return age
    except ValueError as e:
        print(f"Input validation failed: {e}")
        raise  # Re-throw the exception

# Test re-throwing
try:
    age = process_user_input("abc")
except ValueError:
    print("Program could not handle invalid input")

JavaScript Exception Handling

Basic Exception Handling

javascript
// JavaScript - Basic exception handling
function divideNumbers(a, b) {
  try {
    const result = a / b;
    if (!isFinite(result)) {
      throw new Error("Invalid calculation result");
    }
    return result;
  } catch (error) {
    if (error.message === "Invalid calculation result") {
      console.log("Error: Divisor cannot be zero");
    } else {
      console.log("Error: Incorrect parameter type");
    }
    return null;
  }
}

// Test exception handling
console.log(divideNumbers(10, 2)); // 5
console.log(divideNumbers(10, 0)); // Error: Divisor cannot be zero
console.log(divideNumbers("10", 2)); // Error: Incorrect parameter type

// Multiple exception types
function processData(data) {
  try {
    if (typeof data === "string") {
      const result = parseInt(data);
      if (isNaN(result)) {
        throw new Error("Cannot convert to number");
      }
      return result;
    } else if (typeof data === "number") {
      return data;
    } else {
      throw new Error("Unsupported data type");
    }
  } catch (error) {
    console.log(`Data processing error: ${error.message}`);
    return null;
  }
}

// Test multiple exceptions
console.log(processData("123")); // 123
console.log(processData(456)); // 456
console.log(processData("abc")); // Data processing error: Cannot convert to number
console.log(processData([1, 2, 3])); // Data processing error: Unsupported data type

Complete Exception Handling Structure

javascript
// JavaScript - Complete exception handling structure
async function fileOperations(filename) {
  let fileHandle = null;

  try {
    // Try to open the file
    fileHandle = await fs.open(filename, "r");
    const content = await fileHandle.readFile("utf-8");
    console.log("File read successfully");
    return content;
  } catch (error) {
    if (error.code === "ENOENT") {
      console.log(`File ${filename} not found`);
    } else if (error.code === "EACCES") {
      console.log(`No permission to read file ${filename}`);
    } else {
      console.log(`Unknown error: ${error.message}`);
    }
    return null;
  } finally {
    // Always executed, whether an exception occurred or not
    if (fileHandle) {
      await fileHandle.close();
    }
    console.log("Cleaning up resources");
  }
}

// Test file operations
fileOperations("nonexistent.txt");
fileOperations("example.txt");

Exception Chaining and Re-throwing

javascript
// JavaScript - Exception chaining and re-throwing
function lowLevelFunction() {
  try {
    const result = 10 / 0;
    return result;
  } catch (error) {
    throw new Error("Low-level function failed", { cause: error });
  }
}

function highLevelFunction() {
  try {
    lowLevelFunction();
  } catch (error) {
    console.log(`High-level function caught an error: ${error.message}`);
    console.log(`Original error: ${error.cause}`);
  }
}

// Test exception chaining
highLevelFunction();

// Re-throwing an exception
function processUserInput(userInput) {
  try {
    const age = parseInt(userInput);
    if (isNaN(age) || age < 0 || age > 150) {
      throw new Error("Age must be between 0-150");
    }
    return age;
  } catch (error) {
    console.log(`Input validation failed: ${error.message}`);
    throw error; // Re-throw the exception
  }
}

// Test re-throwing
try {
  const age = processUserInput("abc");
} catch (error) {
  console.log("Program could not handle invalid input");
}

Built-in Exceptions

Common Python Exceptions

ExceptionDescription
SyntaxErrorCode syntax error
IndentationErrorIndentation error
NameErrorVariable not found
TypeErrorOperation on inappropriate type
ValueErrorCorrect type, but inappropriate value
IndexErrorIndex out of range for a sequence
KeyErrorDictionary key not found
AttributeErrorAttribute or method not found
FileNotFoundErrorFile not found
ZeroDivisionErrorDivision by zero

Common JavaScript Errors

ErrorDescription
SyntaxErrorCode syntax error
ReferenceErrorInvalid reference (e.g., variable not found)
TypeErrorOperation on inappropriate type
RangeErrorNumber out of allowed range
URIErrorError in URI handling functions

Custom Exceptions

Python Custom Exceptions

python
# Python - Custom exception
class InvalidInputError(ValueError):
    """Custom exception for invalid user input."""
    def __init__(self, message="Invalid input provided"):
        self.message = message
        super().__init__(self.message)

def validate_username(username):
    if not isinstance(username, str) or not username.isalnum():
        raise InvalidInputError("Username must be alphanumeric")
    return True

# Test custom exception
try:
    validate_username("user-123")
except InvalidInputError as e:
    print(f"Error: {e}")

JavaScript Custom Errors

javascript
// JavaScript - Custom error
class InvalidInputError extends Error {
  constructor(message = "Invalid input provided") {
    super(message);
    this.name = "InvalidInputError";
  }
}

function validateUsername(username) {
  if (typeof username !== "string" || !/^[a-zA-Z0-9]+$/.test(username)) {
    throw new InvalidInputError("Username must be alphanumeric");
  }
  return true;
}

// Test custom error
try {
  validateUsername("user-123");
} catch (error) {
  if (error instanceof InvalidInputError) {
    console.log(`Error: ${error.message}`);
  } else {
    throw error;
  }
}

Comparison of Exception Handling

FeaturePythonJavaScript
Main Keywordtry...except...else...finallytry...catch...finally
Catching Specific Errorsexcept TypeError:if (error instanceof TypeError)
Getting Error Infoexcept Exception as e:catch (error)
Custom ExceptionsInherit from ExceptionInherit from Error
Exception Chainingraise NewError from old_errornew Error("...", { cause: oldError })

Summary

  • Python: Exception handling is precise, with except blocks for specific exception types.
  • JavaScript: Uses a general catch block, requiring checks on the error object to handle different error types.

Exercises

  1. Write a function that handles ZeroDivisionError.
  2. Create a custom exception and throw it.
  3. Compare how Python and JavaScript handle multiple exception types.

Next Steps

Now you know how to handle exceptions. Next, we'll learn about dependency management.