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.