Error Handling

โœ•

1. โš ๏ธ Exception Handling

    1.1 What is an Exception?
    1. Imagine filling an online form. If you enter wrong information, the website shows an error message instead of crashing. For example, if age should be a number but you type text, the website asks you to correct it. Exception handling in Python works in a similar way. Exception handling helps us handle errors safely and continue the program when possible. An exception is an error that occurs while a program is running. It is also called a runtime error. If an exception is not handled, the program may stop suddenly.
    1.2 Program Crash Without Exception Handling
    1. If we do not handle an exception, Python stops the program when an error occurs. Example without exception handling: num_1 = 10 num_2 = 0result = num_1 / num_2print(result) print("Program finished")Output: ZeroDivisionError: division by zero Here, the program crashes at this line: result = num_1 / num_2 So this line does not run: print("Program finished") ๐Ÿ“Œ Without exception handling, one runtime error can stop the whole program.
    1.3 Same Example With Exception Handling
    1. Now, let us handle the error using try-except. Example with exception handling: try:num_1 = 10num_2 = 0result = num_1 / num_2print(result)except ZeroDivisionError:print("Error: Cannot divide by zero")print("Program finished")Output: Error: Cannot divide by zero Program finished Here, the program does not crash. Python catches the error and runs the except block. After that, the program continues normally. ๐Ÿ“Œ Exception handling helps the program continue even when an expected error occurs.
    1.4 Why Handle Exceptions?
    1. Exception handling is useful because it helps us: โœ… Prevent the program from crashing suddenly โœ… Show user-friendly error messages โœ… Handle invalid input safely โœ… Continue the program when possible โœ… Debug errors more easily Example situations: - User enters text instead of a number - File is missing - Division by zero happens - Dictionary key is missing - List index is out of range
    1.5 Exception Handling Blocks
    1. Python commonly uses these blocks for exception handling: try: Contains code that may raise an exception. except: Handles the exception if it occurs. else: Runs only if no exception occurs. finally: Runs whether an exception occurs or not.

2. ๐Ÿงช try-except

    2.1 Basic Syntax
    1. Syntax: try:# Code that may raise an exceptionexcept ExceptionType:# Code to handle the exceptionExample: try:result = 10 / 0except ZeroDivisionError:print("Cannot divide by zero")Output: Cannot divide by zero
    2.2 Handling ZeroDivisionError
    1. ZeroDivisionError occurs when we divide a number by zero. Example: try:num_1 = 10num_2 = 0result = num_1 / num_2print(result)except ZeroDivisionError:print("Error: Cannot divide by zero")Output: Error: Cannot divide by zero
    2.3 Handling ValueError
    1. ValueError occurs when a function receives the correct data type but an invalid value. Example without exception handling: age = int("abc")print(age)Output: ValueError: invalid literal for int() with base 10: 'abc' Here, the program crashes because "abc" cannot be converted into an integer. Example with exception handling: try:age = int("abc")print(age)except ValueError:print("Error: Please enter a valid number")print("Program continues")Output: Error: Please enter a valid number Program continues ๐Ÿ“Œ With exception handling, the program shows a useful message instead of crashing.
    2.4 Handling Multiple Exceptions
    1. We can use multiple except blocks to handle different errors. Example: try:user_input = input("Enter two numbers separated by comma: ")num_1, num_2 = map(float, user_input.split(","))print(f"{num_1} / {num_2}: {num_1 / num_2}")except ZeroDivisionError:print("Error: Cannot divide by zero")except ValueError:print("Error: Invalid input. Please enter two numbers separated by comma.")except Exception as e:print(f"Other Error: {e}") Here: ZeroDivisionError โžœ handles division by zero. ValueError โžœ handles invalid number input. Exception as e โžœ handles any other unexpected error.

3. โœ… else and finally

    3.1 else Block
    1. The else block runs only if no exception occurs. Example: try:num_1 = 10num_2 = 2result = num_1 / num_2except ZeroDivisionError:print("Error: Cannot divide by zero")else:print("Division performed successfully")print(result)Output: Division performed successfully 5.0 ๐Ÿ“Œ else runs only when the try block does not produce an exception.
    3.2 finally Block
    1. The finally block always runs. It runs whether an exception occurs or not. Example: try:num_1 = 10num_2 = 0result = num_1 / num_2except ZeroDivisionError:print("Error: Cannot divide by zero")finally:print("Execution completed")Output: Error: Cannot divide by zero Execution completed ๐Ÿ“Œ finally is commonly used for cleanup tasks.
    3.3 Full Exception Handling Example
    1. Example: try:user_input = input("Enter two numbers separated by comma: ")num_1, num_2 = map(float, user_input.split(","))print(f"{num_1} / {num_2}: {num_1 / num_2}")except ZeroDivisionError:print("Error: Cannot divide by zero")except ValueError:print("Error: Invalid input. Please enter two numbers separated by comma.")except Exception as e:print(f"Other Error: {e}")else:print("Division performed successfully")finally:print("Execution completed")

4. ๐Ÿงพ Common Exceptions

ExceptionCauseExample
ZeroDivisionErrorDivision or modulo operation is done by zero.10 / 0, 5 % 0
TypeErrorAn operation is applied to an inappropriate data type.5 + "5", len(5)
ValueErrorA function receives the correct type but an invalid value.int("abc"), float("xyz")
KeyErrorA dictionary key is not found.my_dict = {"a": 1} print(my_dict["b"])
IndexErrorA sequence index is out of range.my_list = [1, 2, 3] print(my_list[5])
NameErrorA variable is used before it is defined.print(x)
AssertionErrorAn assert statement fails.assert 2 + 2 == 5

5. ๐Ÿงท Assertions

    5.1 What is Assertion?
    1. An assertion is used to check whether a condition is True. If the condition is True, the program continues normally. If the condition is False, Python raises AssertionError. Assertions are useful for checking assumptions while testing or debugging code. ๐Ÿ“Œ assert is mostly used for testing and debugging assumptions. ๐Ÿ“Œ For normal user input validation, raise proper exceptions like ValueError or TypeError.
    5.2 assert Syntax
    1. Syntax: assert condition, "Error message" Here: condition โžœ Condition that should be True "Error message" โžœ Message shown if condition is False
    5.3 Assertion Example
    1. Example: assert 2 + 2 == 4, "Broken Math" print("First assertion passed")assert 2 + 2 == 5, "Broken Math" print("This line will not run")Output: First assertion passed AssertionError: Broken Math
    5.4 Assertion with Function
    1. Example: def calculate_area_of_rectangle(length, width):assert length > 0, "Length must be a positive number"assert width > 0, "Width must be a positive number"return length * widtharea = calculate_area_of_rectangle(5, 2) print(f"Area of rectangle: {area}")Output: Area of rectangle: 10 Example with invalid value: area = calculate_area_of_rectangle(-5, 2) print(f"Area of rectangle: {area}")Output: AssertionError: Length must be a positive number

6. ๐Ÿšจ Raising Exceptions

    6.1 What is raise?
    1. Sometimes, we want to create an error ourselves when invalid data is found. The raise keyword is used to raise an exception manually. This helps us stop wrong data from moving forward in the program. Example situations: - Age cannot be negative - Price cannot be below zero - Name cannot be empty - Input must be a number
    6.2 raise Syntax
    1. Syntax: raise ExceptionType("Error message")Example: raise ValueError("Age cannot be negative")
    6.3 Raising TypeError and ValueError
    1. Example: def check_event_entry(age):if type(age) != int:raise TypeError("Age must be an integer")if age < 0:raise ValueError("Age cannot be negative")if age >= 18:return "Eligible"else:return "Not eligible"print(check_event_entry(18)) # Eligible print(check_event_entry(15)) # Not eligible print(check_event_entry(-5)) # Raises ValueError print(check_event_entry("twenty")) # Raises TypeError ๐Ÿ“Œ Run the error examples one at a time.
    6.4 Raising Exceptions in a Function
    1. Example: def calculate_discount(price, discount):if type(price) not in [int, float]:raise TypeError("Price must be a number")if type(discount) not in [int, float]:raise TypeError("Discount must be a number")if price < 0:raise ValueError("Price cannot be negative")if discount < 0:raise ValueError("Discount cannot be negative")final_price = price - (price * discount / 100)return final_priceprint(calculate_discount(1000, 10)) # 900.0 print(calculate_discount(-1000, 10)) # Raises ValueError ๐Ÿ“Œ Run the error examples one at a time.

7. ๐Ÿ› ๏ธ Error Handling Techniques

    7.1 Use Specific Exceptions
    1. It is better to handle specific exceptions when possible. Good: try:result = 10 / 0except ZeroDivisionError:print("Cannot divide by zero")Less specific: try:result = 10 / 0except Exception:print("Something went wrong") ๐Ÿ“Œ Specific exceptions make errors easier to understand and debug.
    7.2 Avoid Hiding Errors
    1. Do not use broad exception handling everywhere. Avoid this when possible: try:# risky codeexcept Exception:pass This hides the error and makes debugging difficult. Better: try:# risky codeexcept ValueError:print("Invalid value")except TypeError:print("Invalid type")

Practice QuestionsNot started

  1. 1. Error Handling

    Question 1 of 3

      1.1 Practice error handling tasks:
      1. Write a function that takes a string and returns the number of lowercase characters in it. Handle TypeError if the input is not a string.
      2. Write a function that takes mass in kg and volume in cubic meter and returns density. Formula: density = mass / volume. Handle ZeroDivisionError and TypeError where appropriate.
      3. Write a function get_name that accepts a dictionary and returns the value of key name. Handle KeyError if the key is missing.
      4. Write a function get_third_element that accepts a list and returns the third element. Handle IndexError if the list has fewer than three elements.
  2. 2. Raising Exceptions

    Question 2 of 3

      2.1 Practice tasks raising exceptions:
      1. Write a function can_get_adult_pass(age). Rules: - Raise TypeError if age is not an integer. - Raise ValueError if age is below 0. - Raise ValueError if age is above 100. - Return True if age is 18 or above. - Otherwise return False.
      2. Create a function get_age that calculates and returns age when birth year is passed. Rules: - Raise TypeError if birth year is not an integer. - Raise ValueError if birth year is in the future. - Raise ValueError if birth year is too old or unrealistic. - The age returned by the function must be an integer.
      3. Write a function calculate_rectangle_area(length, width). Rules: - Raise TypeError if length or width is not a number. - Raise ValueError if length or width is less than or equal to 0. - Return area of rectangle.
  3. 3. Implementation

    Question 3 of 3

      3.1 You have employee record details in file employee_info.csv. Your company is hosting an event and needs to group employees by age category. Write a program that:
      1. Reads the employee_info.csv file.
      2. Calculates each employee's age using the previously defined get_age function.
      3. Determines whether each employee is an adult or a minor using can_get_adult_pass.
      4. Counts total adults and minors.
      5. Generates a JSON file named event_logistic.json in the following format: {"adult_count": 5, "minor_count": 5}. Use proper exception handling while reading the file, calculating age, and writing JSON output.