feat(curriculum): add Python error handling review page (#60559)

Co-authored-by: Dario <105294544+Dario-DC@users.noreply.github.com>
This commit is contained in:
Kolade Chris 2025-08-06 17:34:30 +01:00 committed by GitHub
parent 922c20e0ef
commit 185a421dae
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -7,13 +7,135 @@ dashedName: review-error-handling
# --description--
## First topic
## Common Errors in Python
Describe
- **SyntaxError**: The error Python raises when your code does not follow its syntax rules. For example, the code `print("Hello there"` will lead to a syntax error with the message, `SyntaxError: '(' was never closed`, because the code is missing a closing parenthesis.
- **NameError**: Python raises a `NameError` when you try to access a variable or function you have not defined. For instance, if you have the line `print(username)` in your code without having a `username` variable defined first, you will get a name error with the message `NameError: name 'username' is not defined`.
- **TypeError**: This is the error Python throws when you perform an operation on two or more incompatible data types. For example, if you try to add a string to a number, you'll get the error `TypeError: can only concatenate str (not "int") to str`.
- **IndexError**: You'll get an `IndexError` if you access an index that does not exist in a list or other sequences like tuple and string. For example, in a `Hello world` string, the index of the last character is `11`. If you go ahead and access a character this way, `greet = "hello world"; print(greet[12])`, you'll get an error with the message `IndexError: string index out of range`.
- **AttributeError**: Python raises this error when you try to use a method or property that does not exist in an object of that type. For example, calling `.append()` on a string like `"hello".append("!")` will lead to an error with the message `AttributeError: 'str' object has no attribute 'append'`.
## Second topic
## Good Debugging Techniques in Python
Describe
- **Using the `print` function**: Inserting `print()` statements around various points in your code while debugging helps you see the values of variables and how your code flows.
- **Using Python's Built-in Debugger (`pdb`)**: Python provides a `pdb` module for debugging. It's a part of the Python's standard library, so it's always available to use. With `pdb`, you can set a trace with the `set_trace()` method so you can start stepping through the code and inspect variables in an interactive way.
- **Leveraging IDE Debugging Tools**: Many integrated development environments (IDEs) and code editors like Pycharm and VS Code offer debugging tools with breakpoints, step execution, variable inspection, and other debugging features.
## Exception Handling
- **`try...except`**: This is used to execute a block of code that might raise an exception. The `try` block is where you anticipate an error might occur, while the `except` block takes a specified exception and runs if that specified error is raised. Here's an example:
```py
try:
print(22 / 0)
except ZeroDivisionError:
print('You can\'t divide by zero!')
# You can't divide by zero!
```
You can also chain multiple `except` blocks so you can handle more types of exceptions:
```py
try:
number = int(input('Enter a number: '))
print(22 / number)
except ZeroDivisionError:
print('You cannot divide by zero!')
# You cannot divide by zero! prints when you enter 0
except ValueError:
print('Please enter a valid number!')
# Please enter a valid number! prints when you enter a string
```
- **`else` and `finally`**: These blocks extend `try...except`. If no exception occurs, the `else` block runs. The `finally` block always runs regardless of errors.
```py
try:
result = 100 / 4
except ZeroDivisionError:
print('You cannot divide by zero!') # This will not run
else:
print(f'Result is {result}') # Result is 25.0
finally:
print('Execution complete!') # Execution complete!
```
- **Exception Object**: This lets you access the exception itself for better debugging and printing the direct error message. To access the exception object, you need to use the `as` keyword. Here's an example:
```py
try:
value = int('This will raise an error')
except ValueError as e:
print(f'Caught an error: {e}')
# Caught an error: invalid literal for int() with base 10: 'This will raise an error'
```
- **The `raise` Statement**: This allows you to manually raise an exception. You can use it to throw an exception when a certain condition is met. Here's an example:
```py
def divide(a, b):
if b == 0:
raise ZeroDivisionError('You cannot divide by zero')
return a / b
```
## Exception Signaling
The `raise` statement is also useful when you create your own custom exceptions, as you can use it to throw an exception with a custom message. Here's an example of that:
```py
class InvalidCredentialsError(Exception):
def __init__(self, message="Invalid username or password"):
self.message = message
super().__init__(self.message)
def login(username, password):
stored_username = "admin"
stored_password = "password123"
if username != stored_username or password != stored_password:
raise InvalidCredentialsError()
return f"Welcome, {username}!"
```
Here's a how you can use the `login` function from the `InvalidCredentialsError` exception:
```py
# failed login attempt
try:
message = login("user", "wrongpassword")
print(message)
except InvalidCredentialsError as e:
print(f"Login failed: {e}")
# successful login attempt
try:
message = login("admin", "password123")
print(message)
except InvalidCredentialsError as e:
# This block is not executed because the login was successful
print(f"Login failed: {e}")
else:
# The else block runs if the 'try' block completes without an exception
print(message)
```
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')
```
# --assignment--