{ "cells": [ { "cell_type": "markdown", "id": "0c6cad46", "metadata": {}, "source": [ "# Python Basics - 07. Errors and Exceptions\n", "\n", "Even the best code encounters unexpected issues: network timeouts, missing files, or invalid user inputs. Rather than having the whole script crash abruptly, Python allows you to handle these \"Exceptions\" gracefully." ] }, { "cell_type": "markdown", "id": "ba03f3b5", "metadata": { "language": "markdown" }, "source": [ "## Download Notebook\n", "\n", "{download}`Download this notebook <07_errors_and_exceptions.ipynb>`\n" ] }, { "cell_type": "markdown", "id": "01dddbd6", "metadata": {}, "source": [ "## 1. Common Exceptions Overview\n", "\n", "Here are a few standard exceptions you might encounter:\n", "- `SyntaxError`: Incorrect Python grammar (must be fixed before running, cannot be caught dynamically in the same block).\n", "- `TypeError`: Operation applied to an inappropriate type (e.g., adding string to int).\n", "- `NameError`: Calling a variable that hasn't been defined.\n", "- `ZeroDivisionError`: Trying to divide by zero.\n", "- `IndexError`: Accessing an out-of-bounds index in a list." ] }, { "cell_type": "markdown", "id": "5480cd2d", "metadata": {}, "source": [ "## 2. Using Try-Except Blocks\n", "\n", "Wrap potentially dangerous code inside a `try` block, and handle the specific error inside an `except` block." ] }, { "cell_type": "code", "execution_count": null, "id": "1fdcea23", "metadata": {}, "outputs": [], "source": [ "try:\n", " # This will cause a zero division error\n", " result = 10 / 0\n", "except ZeroDivisionError:\n", " print(\"Error Successfully Caught: You cannot divide a number by zero!\")\n", "except Exception as e:\n", " # A generic fallback for other unexpected errors\n", " print(f\"Caught unexpected error: {e}\")" ] }, { "cell_type": "markdown", "id": "d80ddfb5", "metadata": {}, "source": [ "## 3. Utilizing Else and Finally\n", "\n", "- `else`: This block is executed **only if** no exception occurs inside the try block.\n", "- `finally`: This block is executed **no matter what**, regardless of whether an exception took place. It is typically used for cleaning up resources (e.g. closing network connections)." ] }, { "cell_type": "code", "execution_count": null, "id": "5d11b1e0", "metadata": {}, "outputs": [], "source": [ "def safe_divide(x, y):\n", " print(f\"\\nAttempting to divide {x} by {y}...\")\n", " try:\n", " result = x / y\n", " except ZeroDivisionError:\n", " print(\"[Exception] Division by zero!\")\n", " return None\n", " else:\n", " # Runs if 'try' succeeds\n", " print(f\"[Else] Division successful, result is: {result}\")\n", " return result\n", " finally:\n", " # Runs in all scenarios\n", " print(\"[Finally] Execution of try-except block is complete.\")\n", "\n", "safe_divide(10, 2)\n", "safe_divide(10, 0)" ] }, { "cell_type": "markdown", "id": "0fb6b9fb", "metadata": {}, "source": [ "## 4. Raising Exceptions Manually\n", "\n", "In your own logic, you can force an error to occur if certain conditions are violated using the `raise` keyword." ] }, { "cell_type": "code", "execution_count": null, "id": "1fecdba8", "metadata": {}, "outputs": [], "source": [ "def register_user(age):\n", " if age < 0:\n", " # We intentionally stop execution and throw our own error\n", " raise ValueError(\"A user's age cannot be negative!\")\n", " print(f\"User registered successfully with age: {age}\")\n", "\n", "try:\n", " register_user(-5)\n", "except ValueError as custom_error:\n", " print(f\"Validation Failed: {custom_error}\")" ] }, { "cell_type": "markdown", "id": "ac835886", "metadata": {}, "source": [ "## 5. Custom Exceptions and Assertions\n", "\n", "Custom exceptions make error handling expressive in larger systems.\n", "`assert` is useful during development to check assumptions, but it should not replace full runtime validation for user-facing programs." ] }, { "cell_type": "code", "execution_count": null, "id": "09d5ffe5", "metadata": {}, "outputs": [], "source": [ "class InvalidScoreError(Exception):\n", " \"\"\"Raised when score is outside valid range [0, 100].\"\"\"\n", "\n", "\n", "def normalize_score(score):\n", " # Validate user input before business logic.\n", " if not (0 <= score <= 100):\n", " # Raise a domain-specific exception for clearer handling.\n", " raise InvalidScoreError(f\"Invalid score: {score}\")\n", " return score / 100\n", "\n", "for value in [95, 120, 75]:\n", " try:\n", " print(f\"Normalized: {normalize_score(value):.2f}\")\n", " except InvalidScoreError as e:\n", " # Catch specific exception type first.\n", " print(f\"Handled custom exception: {e}\")\n", "\n", "# Assertion example\n", "# Useful for development-time sanity checks.\n", "x = 10\n", "assert x > 0, \"x must be positive\"\n", "print(\"Assertion passed\")" ] } ], "metadata": { "language_info": { "name": "python" } }, "nbformat": 4, "nbformat_minor": 5 }