diff --git a/client/i18n/locales/english/intro.json b/client/i18n/locales/english/intro.json index f3f246dedd5..ab708a281c6 100644 --- a/client/i18n/locales/english/intro.json +++ b/client/i18n/locales/english/intro.json @@ -4349,7 +4349,9 @@ }, "lecture-understanding-error-handling": { "title": "Understanding Error Handling", - "intro": ["Learn about Understanding Error Handling in these lectures."] + "intro": [ + "In these lectures, you will learn about error handling in Python. You will learn about the different types of errors, some good debugging practices, what exceptions are, and how to handle them." + ] }, "lab-isbn-validator": { "title": "Debug an ISBN Validator", diff --git a/client/src/pages/learn/full-stack-developer/lecture-understanding-error-handling/index.md b/client/src/pages/learn/full-stack-developer/lecture-understanding-error-handling/index.md index 5670e0a2eed..7f8ce6622d8 100644 --- a/client/src/pages/learn/full-stack-developer/lecture-understanding-error-handling/index.md +++ b/client/src/pages/learn/full-stack-developer/lecture-understanding-error-handling/index.md @@ -6,4 +6,4 @@ superBlock: full-stack-developer ## Introduction to Understanding Error Handling -Learn about Understanding Error Handling in these lectures. +In these lectures, you will learn about error handling in Python. You will learn about the different types of errors, some good debugging practices, what exceptions are, and how to handle them. diff --git a/curriculum/challenges/english/blocks/lecture-understanding-error-handling/68420bacf395f15cd73f8118.md b/curriculum/challenges/english/blocks/lecture-understanding-error-handling/68420bacf395f15cd73f8118.md index 6a6ae04446d..b39f02aab80 100644 --- a/curriculum/challenges/english/blocks/lecture-understanding-error-handling/68420bacf395f15cd73f8118.md +++ b/curriculum/challenges/english/blocks/lecture-understanding-error-handling/68420bacf395f15cd73f8118.md @@ -1,135 +1,172 @@ --- id: 68420bacf395f15cd73f8118 -# title needs to be updated to correct title when lectures are finalized -title: Understanding Error Handling +title: What Are Some Common Error Messages in Python? challengeType: 19 -# dashedName needs to be updated to correct title when lectures are finalized -dashedName: lecture-understanding-error-handling +dashedName: what-are-some-common-error-messages-in-python --- # --description-- -Watch the video or read the transcript and answer the questions below. +When writing Python code, it's common to run into errors. Understanding these errors is key to debugging your code quickly and efficiently. These messages tell you exactly what went wrong, if you know how to read them. + +Common Python errors include `SyntaxError`, `NameError`, `TypeError`, `IndexError`, and `AttributeError`. These occur when Python doesn't understand your code, or when your logic doesn't match the data you're working with. + +Here is an example of a `SyntaxError`: + +```py +print("Hello, world!" +# SyntaxError: unexpected EOF while parsing +``` + +This line is missing a closing parenthesis. Python raises a `SyntaxError` because the code doesn't follow proper syntax rules. + +Here is an example of a `NameError`: + +```py +print(name) +# NameError: name 'name' is not defined +``` + +You're trying to print a variable that hasn't been defined yet. Python raises a `NameError` when it can't find a variable by that name. + +Here is an example of a `TypeError`: + +```py +5 + "5" +# TypeError: unsupported operand type(s) for +: 'int' and 'str' +``` + +You can't add an integer and a string together. Python raises a `TypeError` when you try to perform an operation on incompatible data types. + +Here is an example of an `IndexError`: + +```py +my_list = [1, 2, 3] +print(my_list[5]) +# IndexError: list index out of range +``` + +You're trying to access an index that doesn't exist in the list. Python raises an `IndexError` when you go out of bounds. + +Here is an example of an `AttributeError`: + +```py +num = 42 +num.append(5) +# AttributeError: 'int' object has no attribute 'append' +``` + +The `int` object doesn't have an `append()` method. Python raises an `AttributeError` when you try to use a method or property that doesn't exist for that data type. + +Recognizing common Python error messages helps you fix problems faster. Instead of guessing, read the error message carefully, it often tells you exactly what went wrong and where to look. + # --questions-- ## --text-- -Question 1 +What does a `NameError` mean in Python? ## --answers-- -Answer 1.1 +A variable is misspelled. ### --feedback-- -Feedback 1 +Refer back to the section of the lecture on `NameError`. --- -Answer 1.2 - -### --feedback-- - -Feedback 1 +A variable is not defined. --- -Answer 1.3 +An index is out of range. ### --feedback-- -Feedback 1 +Refer back to the section of the lecture on `NameError`. --- -Answer 1.4 +A data type is incorrect. ### --feedback-- -Feedback 1 +Refer back to the section of the lecture on `NameError`. ## --video-solution-- -5 +2 ## --text-- -Question 2 +Which error occurs when trying to add an integer to a string? ## --answers-- -Answer 2.1 +`NameError` ### --feedback-- -Feedback 2 +Refer back to type errors in the lecture. --- -Answer 2.2 +`SyntaxError` ### --feedback-- -Feedback 2 +Refer back to type errors in the lecture. --- -Answer 2.3 - -### --feedback-- - -Feedback 2 +`TypeError` --- -Answer 2.4 +`AttributeError` ### --feedback-- -Feedback 2 +Refer back to type errors in the lecture. ## --video-solution-- -5 +3 ## --text-- -Question 3 +What causes an `IndexError`? ## --answers-- -Answer 3.1 +A function is missing. ### --feedback-- -Feedback 3 +Refer back to the section on `IndexError` in the lecture. --- -Answer 3.2 +A string is not formatted correctly. ### --feedback-- -Feedback 3 +Refer back to the section on `IndexError` in the lecture. --- -Answer 3.3 - -### --feedback-- - -Feedback 3 +Accessing an element outside the bounds of an iterable. --- -Answer 3.4 +Using an undefined variable. ### --feedback-- -Feedback 3 +Refer back to the section on `IndexError` in the lecture. ## --video-solution-- -5 - +3 diff --git a/curriculum/challenges/english/blocks/lecture-understanding-error-handling/688c8ef26f3cad09f36b95b9.md b/curriculum/challenges/english/blocks/lecture-understanding-error-handling/688c8ef26f3cad09f36b95b9.md new file mode 100644 index 00000000000..211fc7dca0d --- /dev/null +++ b/curriculum/challenges/english/blocks/lecture-understanding-error-handling/688c8ef26f3cad09f36b95b9.md @@ -0,0 +1,258 @@ +--- +id: 688c8ef26f3cad09f36b95b9 +title: What Are Some Good Debugging Techniques in Python? +challengeType: 19 +dashedName: what-are-some-good-debugging-techniques-in-python +--- + +# --description-- + +Debugging is an essential skill for any Python developer. Understanding foundational techniques can help you identify and fix issues efficiently. + +Debugging is the process of identifying and resolving errors or bugs in your code. It involves examining the code, understanding the flow, and using tools to pinpoint the source of problems. + +In this lecture, we'll go over common debugging techniques you can use in your next Python project. + +## Using the print function and f-strings + +First, using the `print()` function and f-strings at various points in your code can help you understand the flow and state of variables. For example: + +```py +def add(a, b): + result = a + b + print(f'Adding {a} and {b} gives {result}') + return result +``` + +By printing the values of `a`, `b`, and `result`, you can verify that the function behaves as expected. + +## Interactive Debugging with the `pdb` Module + +Next, you can utilize Python's built-in `pdb` module for interactive debugging: + +```py +import pdb + +def divide(a, b): + pdb.set_trace() + return a / b + +print(divide(10, 2)) +``` + +By setting a trace with the `.set_trace()` method, you can step through the code, inspect variables, and understand the program's behavior. + +If you run the code above, you'll see some output showing the location of the file you're running, the line where you called the `.set_trace()` method and the code immediately after it, and an interactive `pdb` prompt: + +```py +> /Users/fcc/Desktop/lecture.py(5)divide() +-> return a / b +(Pdb) +``` + +If you enter help into the prompt, you'll see a list of commands you can use: + +```py +(Pdb) help + +Documented commands (type help ): +======================================== +EOF c d h list q rv undisplay +a cl debug help ll quit s unt +alias clear disable ignore longlist r source until +args commands display interact n restart step up +b condition down j next return tbreak w +break cont enable jump p retval u whatis +bt continue exit l pp run unalias where + +Miscellaneous help topics: +========================== +exec pdb +``` + +Then you can use the commands to debug your code. + +For example, if you want to look at the type of elements throughout your code at that moment, you can use the `whatis` command: + +```py +(Pdb) whatis a + +(Pdb) whatis divide +Function divide +``` + +As you can see, by the time you run `.set_trace()`, the type of the parameter a is an integer, and divide is a function. + +Then to continue execution of your code, you can use the `continue` command, or one of its aliases, `cont` or `c`: + +```py +(Pdb) continue +5.0 +``` + +## IDE Debugging Tools + +Many Integrated Development Environments (IDEs) offer advanced debugging tools, such as breakpoints, step execution, and variable inspection. + +## Using VS Code Debugger + +If you use VS Code, you can set breakpoints in your code and run the debugger to pause execution at those points. Here's how to debug the same `divide` function: + +**Step 1: Set up your code** Create a file called `main.py` with the following content: + +```py +def divide(a, b): + result = a / b + return result + +print(divide(10, 2)) +print(divide(15, 3)) +``` + +**Step 2: Set a breakpoint** + +1. Click in the gutter (left margin) next to line 2 (`result = a / b`) to set a breakpoint + +2. A red dot will appear, indicating the breakpoint is set + +**Step 3: Start debugging** + +1. Press `F5` or go to Run > Start Debugging + +2. Select "Python File" when prompted + +3. The debugger will pause execution at your breakpoint + +**Step 4: Inspect variables** + +- Hover over variables to see their current values + +- Use the Variables panel on the left to see all local variables + +- Use the Debug Console at the bottom to evaluate expressions + +**Step 5: Step through code** + +Use the debug toolbar to: + +- **Continue (F5)**: Resume execution until the next breakpoint + +- **Step Over (F10)**: Execute the current line and move to the next + +- **Step Into (F11)**: Enter into function calls + +- **Step Out (Shift+F11)**: Exit the current function + +IDE debugging tools provide a visual interface to examine the state of your program, making it easier to identify and fix issues compared to using print statements alone. + +By mastering these foundational debugging techniques - using `print()` statements, the pdb module, and IDE tools - you can effectively identify and resolve issues in your Python code. Each technique has its place: `print()` statements for quick checks, pdb for interactive exploration, and IDE debuggers for visual inspection. + +# --questions-- + +## --text-- + +What is the purpose of using the `print()` function in debugging? + +## --answers-- + +To execute code faster + +### --feedback-- + +Refer back to the section where `print()` is discussed. + +--- + +To display variable values and program flow + +--- + +To compile the code + +### --feedback-- + +Refer back to the section where `print()` is discussed. + +--- + +To terminate the program + +### --feedback-- + +Refer back to the section where `print()` is discussed. + +## --video-solution-- + +2 + +## --text-- + +What does the `pdb` module in Python provide? + +## --answers-- + +A graphical user interface + +### --feedback-- + +Refer back to the section where `pdb` is discussed. + +--- + +A way to compile Python code + +### --feedback-- + +Refer back to the section where `pdb` is discussed. + +--- + +An interactive debugging environment + +--- + +A method to encrypt code + +### --feedback-- + +Refer back to the section where `pdb` is discussed. + +## --video-solution-- + +3 + +## --text-- + + What advantage do IDE debugging tools have over other methods like `print()` statements? + +## --answers-- + +They let you write code faster. + +### --feedback-- + +Refer back to the section where IDE debugging tools are discussed. + +--- + +They prevent syntax errors. + +### --feedback-- + +Refer back to the section where IDE debugging tools are discussed. + +--- + +They fix bugs in your code automatically. + +### --feedback-- + +Refer back to the section where IDE debugging tools are discussed. + +--- + +They provide a visual interface to inspect the state of your program. + +## --video-solution-- + +4 diff --git a/curriculum/challenges/english/blocks/lecture-understanding-error-handling/688c9c3313b264122a694a08.md b/curriculum/challenges/english/blocks/lecture-understanding-error-handling/688c9c3313b264122a694a08.md new file mode 100644 index 00000000000..c16bd14d701 --- /dev/null +++ b/curriculum/challenges/english/blocks/lecture-understanding-error-handling/688c9c3313b264122a694a08.md @@ -0,0 +1,191 @@ +--- +id: 688c9c3313b264122a694a08 +title: How Does Exception Handling Work? +challengeType: 19 +dashedName: how-does-exception-handling-work +--- + +# --description-- + +In Python, exception handling is a core part of writing robust and fault-tolerant programs. It allows you to anticipate, catch, and respond to errors in a structured way. + +Exception handling is the process of catching and managing errors that occur during the execution of a program, so your code doesn't crash unexpectedly. + +Python provides the `try`, `except`, `else`, and `finally` blocks to gracefully handle errors. Here's a basic example: + +```py +try: + x = 10 / 0 +except ZeroDivisionError: + print("You can't divide by zero!") +``` + +- `try`: The block of code where you anticipate an error might occur. + +- `except`: This block runs if an error of the specified type is raised inside the try. + +- In this case, dividing by zero raises a `ZeroDivisionError`, which is then caught and handled. + +And here's an example also showing how to use the `else` and `finally` blocks: + +```py +try: + x = 10 / 2 +except ZeroDivisionError: + print("You can't divide by zero!") +else: + print('Division successful:', x) +finally: + print('This block always runs.') +``` + +- `else`: Runs if no exception is raised in the try block. + +- `finally`: Runs no matter what—whether or not an exception occurred. Useful for clean-up tasks like closing files or releasing resources. + +You can also catch multiple exceptions with separate `except` blocks: + +```py +try: + number = int('abc') + result = 10 / number +except ValueError: + print('That was not a valid number.') +except ZeroDivisionError: + print("Can't divide by zero.") +``` + +By using separate `except` clauses, you can make your error responses more specific and useful. + +You can also use the exception object, which is typically aliased to another name with the `as` keyword. Here we're using `e` as an alias for the error object: + +```py +try: + x = 1 / 0 +except ZeroDivisionError as e: + print(f'Error occurred: {e}') +``` + +Using `e` lets you access the actual error message or object for logging or debugging. + +You can also catch multiple exceptions in a single `except` clause by specifying the exceptions as a tuple: + +```py +try: + number = int(input('Enter a number: ')) + result = 10 / number +except (ValueError, ZeroDivisionError) as e: + print(f'Error occurred: {e}') +``` + +Exception handling allows your programs to recover from errors gracefully. By using `try`, `except`, `else`, and `finally`, you can anticipate potential issues and build more resilient applications. + +# --questions-- + +## --text-- + +What does the `try` block do in Python? + +## --answers-- + +It ignores errors completely. + +### --feedback-- + +Refer back to the section about `try` and `except` blocks. + +--- + +It defines a block of code to test for errors. + +--- + +It deletes all exceptions. + +### --feedback-- + +Refer back to the section about `try` and `except` blocks. + +--- + +It stops the program immediately. + +### --feedback-- + +Refer back to the section about `try` and `except` blocks. + +## --video-solution-- + +2 + +## --text-- + +When does the `finally` block execute? + +## --answers-- + +Only when there is no error + +### --feedback-- + +Refer back to the section about the `finally` block. + +--- + +Only when an exception occurs + +### --feedback-- + +Refer back to the section about the `finally` block. + +--- + +Always, no matter what + +--- + +Only if the `else` block executes + +### --feedback-- + +Refer back to the section about the `finally` block. + +## --video-solution-- + +3 + +## --text-- + +Which statement is used to catch a specific error? + +## --answers-- + +`handle` + +### --feedback-- + +Refer back to beginning of the lecture about Python error handling. + +--- + +`catch` + +### --feedback-- + +Refer back to beginning of the lecture about Python error handling. + +--- + +`try` + +### --feedback-- + +Refer back to beginning of the lecture about Python error handling. + +--- + +`except` + +## --video-solution-- + +4 diff --git a/curriculum/challenges/english/blocks/lecture-understanding-error-handling/688c9c4fe5fef91262f9bdf8.md b/curriculum/challenges/english/blocks/lecture-understanding-error-handling/688c9c4fe5fef91262f9bdf8.md new file mode 100644 index 00000000000..5a12e33bebb --- /dev/null +++ b/curriculum/challenges/english/blocks/lecture-understanding-error-handling/688c9c4fe5fef91262f9bdf8.md @@ -0,0 +1,248 @@ +--- +id: 688c9c4fe5fef91262f9bdf8 +title: What Is the Raise Statement and How Does It Work? +challengeType: 19 +dashedName: what-is-the-raise-statement-and-how-does-it-work +--- + +# --description-- + +In Python, the `raise` statement is a powerful tool that allows you to manually trigger exceptions in your code. It gives you control over when and how errors are generated, enabling you to create custom error conditions and enforce specific program behavior. + +The `raise` statement is used to explicitly throw an exception at any point in your program, allowing you to signal that an error condition has occurred or that certain requirements haven't been met. + +Python's `raise` statement can be used in several ways to trigger exceptions. At its most basic, you can raise built-in exceptions or create custom error messages. Here's a simple example: + +```py +def check_age(age): + if age < 0: + raise ValueError('Age cannot be negative') + return age + +try: + check_age(-5) +except ValueError as e: + print(f'Error: {e}') # Error: Age cannot be negative +``` + +You can see here that `raise` is the keyword that triggers an exception. + +In this example, we're raising a `ValueError` with a custom message when an invalid age is provided. + +The `raise` statement can also be used to re-raise the current exception, which is particularly useful in exception handling: + +```py +def process_data(data): + try: + result = int(data) + return result * 2 + except ValueError: + print('Logging: Invalid data received') + raise # Re-raises the same ValueError + +try: + process_data('abc') +except ValueError: + print('Handled at higher level') +``` + +Here the keyword `raise` (without arguments), re-raises the current exception that's being handled. + +This allows you to log or perform cleanup while still propagating the error up the call stack. + +You can create and raise custom exceptions by defining your own exception classes: + +```py +class InsufficientFundsError(Exception): + def __init__(self, balance, amount): + self.balance = balance + self.amount = amount + super().__init__(f'Insufficient funds: ${balance} available, ${amount} requested') + +def withdraw(balance, amount): + if amount > balance: + raise InsufficientFundsError(balance, amount) + return balance - amount + +try: + new_balance = withdraw(100, 150) +except InsufficientFundsError as e: + print(f'Transaction failed: {e}') +``` + +Here you can see custom exception classes inherit from `Exception` or its subclasses. + +You'll learn more about classes and inheritance in future lectures. For now, know that this is a way to create your own exceptions with custom logic. + +The `raise` statement can also be used with the `from` keyword to chain exceptions, showing the relationship between different errors: + +```py +def parse_config(filename): + try: + with open(filename, 'r') as file: + data = file.read() + return int(data) + except FileNotFoundError: + raise ValueError('Configuration file is missing') from None + except ValueError as e: + raise ValueError('Invalid configuration format') from e + +config = parse_config('config.txt') +``` + +Here you can see that `raise ... from None`, suppresses the original exception context: + +```bash +Traceback (most recent call last): + File "main.py", line 12, in + config = parse_config('config.txt') + ^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "main.py", line 7, in parse_config + raise ValueError('Configuration file is missing') from None +ValueError: Configuration file is missing +``` + +And `raise ... from e`, chains the new exception to the original one, preserving the error trail. + +```bash +Traceback (most recent call last): + File "main.py", line 5, in parse_config + return int(data) + ^^^^^^^^^ +ValueError: invalid literal for int() with base 10: '' + +The above exception was the direct cause of the following exception: + +Traceback (most recent call last): + File "main.py", line 12, in + config = parse_config('config.txt') + ^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "main.py", line 9, in parse_config + raise ValueError('Invalid configuration format') from e +ValueError: Invalid configuration format +``` + +You can also raise exceptions conditionally using `assert` statements, which are essentially shorthand for `raise` with `AssertionError`: + +```py +def calculate_square_root(number): + assert number >= 0, 'Cannot calculate square root of negative number' + return number ** 0.5 + +try: + result = calculate_square_root(-4) +except AssertionError as e: + print(f'Assertion failed: {e}') +``` + +The `raise` statement is essential for creating robust applications where you need to enforce business rules, validate input, and provide meaningful error messages. By strategically using `raise`, you can make your code more predictable and easier to debug, while giving users clear feedback about what went wrong. + +# --questions-- + +## --text-- + +What does the `raise` statement do in Python? + +## --answers-- + +It catches exceptions. + +### --feedback-- + +Refer back to the section about raising exceptions. + +--- + +It manually triggers an exception. + +--- + +It ignores errors. + +### --feedback-- + +Refer back to the section about raising exceptions. + +--- + +It fixes broken code. + +### --feedback-- + +Refer back to the section about raising exceptions. + +## --video-solution-- + +2 + +## --text-- + +What happens when you use `raise` without any arguments? + +## --answers-- + +It raises a generic `Exception`. + +### --feedback-- + +Refer back to the section about `raise`. understand how it behaves without arguments. + +--- + +It does nothing. + +### --feedback-- + +Refer back to the section about `raise`. understand how it behaves without arguments. + +--- + +It re-raises the current exception. + +--- + +It raises a `TypeError`. + +### --feedback-- + +Refer back to the section about `raise`. understand how it behaves without arguments. + +## --video-solution-- + +3 + +## --text-- + +Which keyword is used to chain exceptions together? + +## --answers-- + +`with` + +### --feedback-- + +Refer back to the section about `raise` to understand which keyword connects exceptions. + +--- + +`from` + +--- + +`chain` + +### --feedback-- + +Refer back to the section about `raise` to understand which keyword connects exceptions. + +--- + +`link` + +### --feedback-- + +Refer back to the section about `raise` to understand which keyword connects exceptions. + +## --video-solution-- + +2 diff --git a/curriculum/structure/blocks/lecture-understanding-error-handling.json b/curriculum/structure/blocks/lecture-understanding-error-handling.json index b2444dc9d45..18bedae5d72 100644 --- a/curriculum/structure/blocks/lecture-understanding-error-handling.json +++ b/curriculum/structure/blocks/lecture-understanding-error-handling.json @@ -1,10 +1,27 @@ { "name": "Understanding Error Handling", - "isUpcomingChange": true, - "dashedName": "lecture-understanding-error-handling", "blockType": "lecture", "blockLayout": "challenge-list", + "isUpcomingChange": true, + "dashedName": "lecture-understanding-error-handling", "superBlock": "full-stack-developer", - "challengeOrder": [{ "id": "68420bacf395f15cd73f8118", "title": "Step 1" }], - "helpCategory": "Python" + "helpCategory": "Python", + "challengeOrder": [ + { + "id": "68420bacf395f15cd73f8118", + "title": "What Are Some Common Error Messages in Python?" + }, + { + "id": "688c8ef26f3cad09f36b95b9", + "title": "What Are Some Good Debugging Techniques in Python?" + }, + { + "id": "688c9c3313b264122a694a08", + "title": "How Does Exception Handling Work?" + }, + { + "id": "688c9c4fe5fef91262f9bdf8", + "title": "What Is the Raise Statement and How Does It Work?" + } + ] }