Unit 4: Modules and Exception Handling - Subjective Questions
CSR101 — Python Programming • Practice Questions with Detailed Answers
20 questions
Explain the purpose of exception handling in Python. Describe the syntax and execution flow of a try and except block with a suitable example.
Exception handling allows a program to respond to runtime errors without terminating abruptly.
A basic structure is:
try:
number = int(input("Enter a number: "))
result = 10 / number
except ZeroDivisionError:
print("Division by zero is not allowed.")
except ValueError:
print("Please enter a valid integer.")- Statements that may produce an exception are placed inside the
tryblock. - If an exception occurs, Python searches for a matching
exceptblock. - The remaining statements in the
tryblock are skipped after the exception. - If no exception occurs, all
exceptblocks are skipped. - Handling errors improves program reliability and user experience.
What are multiple exception handlers? Explain how Python selects an appropriate handler when more than one type of exception may occur.
Multiple exception handlers are used when a block of code can generate different types of errors.
try:
value = int(input("Enter a value: "))
result = 100 / value
except ValueError:
print("The input is not an integer.")
except ZeroDivisionError:
print("The value cannot be zero.")
except Exception as error:
print("An unexpected error occurred:", error)- Python checks the
exceptclauses from top to bottom. - The first handler whose exception type matches the raised exception is executed.
- More specific exceptions should be placed before general exceptions such as
Exception. - The general
Exceptionhandler should not hide errors unnecessarily. - Multiple handlers make error messages more precise and meaningful.
Explain how the else clause can be used with exception handling. Compare the roles of try, except, else, and finally.
The else clause executes only when the try block completes without raising an exception.
try:
file = open("data.txt", "r")
except FileNotFoundError:
print("File does not exist.")
else:
print(file.read())
finally:
print("File-processing attempt completed.")try: Contains statements that may cause an exception.except: Handles a matching exception.else: Runs only when no exception occurs in thetryblock.finally: Runs whether an exception occurs or not.
Using else keeps successful-operation code separate from error-handling code and improves readability.
Describe how exceptions are raised explicitly in Python. Explain the use of the raise statement with examples.
The raise statement is used to generate an exception explicitly when a program detects an invalid condition.
def set_age(age):
if age < 0:
raise ValueError("Age cannot be negative")
return ageAn exception can also be re-raised inside a handler:
try:
value = int("abc")
except ValueError:
print("Logging the input error")
raiseraise ExceptionType("message")creates and raises an exception.- It is useful for validating arguments and enforcing program rules.
- Re-raising preserves the original exception and allows higher-level code to handle it.
- Meaningful error messages make debugging easier.
Explain how exceptions are propagated through functions. Illustrate the difference between handling an exception inside a function and allowing the caller to handle it.
When an exception is not handled inside a function, it propagates to the function that called it. This continues until a matching handler is found.
def calculate(value):
return 100 / value
def process():
try:
print(calculate(0))
except ZeroDivisionError:
print("The caller handled the error.")
process()Alternatively, the function itself may handle the error:
def calculate(value):
try:
return 100 / value
except ZeroDivisionError:
return NoneA function should handle an exception when it can recover meaningfully. Otherwise, it should allow the caller to handle the problem, possibly after adding context or logging information.
Explain the purpose of the finally block. Why is it important for resource cleanup? Provide a suitable example.
The finally block contains code that must execute regardless of whether an exception occurs.
file = None
try:
file = open("report.txt", "r")
data = file.read()
except OSError as error:
print("File error:", error)
finally:
if file is not None:
file.close()
print("Cleanup completed.")The finally block is useful for:
- Closing files.
- Releasing database connections.
- Closing network sockets.
- Releasing locks.
- Restoring temporary program state.
It executes after the try and any matching except or else block, even when an exception is not handled.
What are custom exception types? Explain how to define and use a user-defined exception class in Python.
A custom exception is a programmer-defined class used to represent an application-specific error. It normally inherits from Exception.
class InsufficientBalanceError(Exception):
"""Raised when an account lacks sufficient funds."""
pass
def withdraw(balance, amount):
if amount > balance:
raise InsufficientBalanceError("Insufficient account balance")
return balance - amount
try:
balance = withdraw(500, 800)
except InsufficientBalanceError as error:
print(error)Advantages include:
- Expressing domain-specific problems clearly.
- Allowing separate handling of different application errors.
- Improving code readability and maintainability.
- Carrying meaningful error messages or additional attributes.
Design a Python program that validates a student's marks using a custom exception and handles invalid input gracefully.
A custom exception can represent marks that are outside the permitted range.
class InvalidMarksError(Exception):
pass
def validate_marks(marks):
if not 0 <= marks <= 100:
raise InvalidMarksError("Marks must be between 0 and 100")
return marks
try:
marks = float(input("Enter marks: "))
validate_marks(marks)
print("Valid marks:", marks)
except ValueError:
print("Enter a numeric value.")
except InvalidMarksError as error:
print(error)
finally:
print("Validation process completed.")The program uses:
- A custom exception for domain-specific validation.
ValueErrorfor nonnumeric input.- Separate handlers for different error types.
finallyfor a message or other cleanup action.
Define a Python module. Explain the advantages of using modules in program development.
A module is a Python file containing definitions such as functions, classes, variables, and executable statements. Its filename normally ends with .py.
For example, geometry.py may contain:
def area_rectangle(length, width):
return length * widthAdvantages of modules include:
- Modularity: Large programs can be divided into smaller components.
- Reusability: Definitions can be imported into multiple programs.
- Maintainability: Changes can be made in one place.
- Namespace management: Names in one module do not automatically conflict with names in another.
- Testing: Individual modules can be tested independently.
- Collaboration: Different programmers can work on separate modules.
Explain how Python finds modules to import. Discuss the role of the current directory, sys.path, and installed packages.
When Python executes an import statement, it searches for the requested module in locations listed in sys.path.
import sys
print(sys.path)The search commonly includes:
- The directory containing the running script.
- The current working directory in interactive use.
- Directories listed in the
PYTHONPATHenvironment variable. - Standard-library directories.
- Site-packages directories containing installed third-party packages.
If no matching module is found, Python raises ModuleNotFoundError.
A module can be found by:
import math
print(math.__file__)Good practice is to avoid naming a user file after a standard module, such as random.py or datetime.py, because it may shadow the intended module.
Compare the different forms of importing modules in Python, including import module, from module import name, and aliased imports.
Python provides several import styles.
import math
print(math.sqrt(25))This imports the module and requires qualified names.
from math import sqrt, pi
print(sqrt(25))This imports selected names directly into the current namespace.
import datetime as dt
print(dt.date.today())This assigns an alias to a module.
Comparison:
import moduleclearly shows where a name originates.from module import nameis concise but may cause name conflicts.- Aliases improve readability or avoid long module names.
from module import *is generally discouraged because it makes the origin of names unclear and may overwrite existing names.
Explain how to execute a module both as an imported module and as a standalone script. Describe the purpose of if __name__ == "__main__".
A Python file can be used as an importable module and as a standalone script.
def greet(name):
return f"Hello, {name}"
if __name__ == "__main__":
print(greet("User"))When the file is run directly, Python sets __name__ to "__main__", so the guarded code executes. When the file is imported, __name__ becomes the module's name, so the guarded code does not execute.
Benefits include:
- Preventing test or demonstration code from running during import.
- Allowing one file to provide reusable functions and a command-line interface.
- Separating definitions from program execution.
- Supporting simple module-level testing.
What is module reloading? Explain when it may be useful and describe one way to reload an already imported module.
Module reloading means executing the module's code again after it has already been imported. It can be useful during interactive development when a module is edited and the programmer wants to test changes without restarting the interpreter.
import mymodule
from importlib import reload
reload(mymodule)Important points:
reload()updates the module object by executing its source code again.- Existing references imported directly with
from mymodule import functionmay not automatically refer to the updated function. - Reloading does not always reset every object or external resource created by the module.
- It should be used carefully in production programs because state and references may become inconsistent.
- Restarting the interpreter is often safer when major changes are made.
Define a Python package and explain how packages organize modules. Include an example package structure and an import statement.
A package is a directory that organizes related Python modules and subpackages under a common namespace.
Example structure:
shop/
__init__.py
products.py
orders.py
utilities/
__init__.py
formatting.pyPossible imports are:
from shop.products import calculate_price
from shop.utilities.formatting import format_currencyPackages provide:
- Logical organization of large projects.
- Hierarchical namespaces.
- Better separation of responsibilities.
- Easier distribution and reuse of related modules.
- Reduced naming conflicts.
In modern Python, a regular package commonly contains __init__.py, although namespace packages can exist without it.
Explain the Python standard library and discuss the uses of any five commonly used standard-library modules.
The Python standard library is a collection of modules distributed with Python. It provides reusable functionality without requiring separate installation.
Examples include:
math: Mathematical functions such assqrt()andceil().os: Operating-system interaction, paths, and environment variables.sys: Interpreter-related information and command-line arguments.json: Encoding and decoding JSON data.re: Regular-expression processing.random: Generation of pseudorandom values.collections: Specialized container types.pathlib: Object-oriented filesystem paths.
Using standard-library modules reduces development time, promotes tested solutions, and avoids rewriting commonly needed functionality.
Describe the datetime module. Explain the difference between date, time, datetime, and timedelta objects with examples.
The datetime module provides classes for representing and manipulating dates and times.
from datetime import date, time, datetime, timedelta
birthday = date(2000, 5, 15)
class_time = time(10, 30)
now = datetime.now()
tomorrow = now + timedelta(days=1)daterepresents a calendar date: year, month, and day.timerepresents a time of day: hour, minute, second, and microsecond.datetimecombines a date and a time.timedeltarepresents a duration or difference between dates and times.
Dates and times can be formatted using strftime() and parsed from strings using strptime().
Write a detailed explanation of date formatting and parsing using the datetime module. Include at least four format directives.
Formatting converts a date or time object into a string using strftime(). Parsing converts a string into a date or time object using strptime().
from datetime import datetime
value = datetime(2024, 7, 20, 14, 45)
formatted = value.strftime("%d-%m-%Y %H:%M")
print(formatted)
parsed = datetime.strptime("20-07-2024 14:45", "%d-%m-%Y %H:%M")
print(parsed)Common directives include:
%Y: Four-digit year.%m: Two-digit month.%d: Day of the month.%H: Hour in 24-hour format.%M: Minute.%S: Second.
The format supplied to strptime() must match the input string; otherwise, a ValueError is raised.
Design a modular program that reads a date string, calculates an expiry date, and handles invalid date input using exception handling.
A modular solution separates date parsing and expiry calculation from user interaction.
from datetime import datetime, timedelta
class InvalidDateError(Exception):
pass
def calculate_expiry(date_text, validity_days):
try:
start = datetime.strptime(date_text, "%Y-%m-%d")
except ValueError as error:
raise InvalidDateError("Date must use YYYY-MM-DD format") from error
return start + timedelta(days=validity_days)
def main():
try:
result = calculate_expiry("2024-02-30", 30)
print(result.strftime("%Y-%m-%d"))
except InvalidDateError as error:
print("Invalid input:", error)
finally:
print("Operation completed.")
if __name__ == "__main__":
main()This design demonstrates modular functions, a custom exception, exception chaining with from, date arithmetic, a main guard, and guaranteed completion logic.
Explain exception chaining in Python. Why might the raise NewException(...) from original_error syntax be useful?
Exception chaining records that one exception was caused by another. It is useful when a lower-level error must be converted into a meaningful higher-level error without losing the original cause.
def read_configuration(path):
try:
with open(path, "r") as file:
return file.read()
except OSError as error:
raise ConfigurationError("Unable to load configuration") from error
class ConfigurationError(Exception):
passBenefits include:
- Presenting an application-specific error to the caller.
- Preserving the original exception for debugging.
- Showing a clear causal relationship in the traceback.
- Separating low-level implementation details from high-level program logic.
The from clause explicitly identifies the original cause.
Discuss common principles for writing modular, maintainable, and error-resilient Python code.
Good Python programs are organized so that each component has a clear responsibility and failures are handled predictably.
Important principles are:
- Divide code into focused modules and functions.
- Use meaningful names, docstrings, and consistent formatting.
- Keep functions small and avoid unnecessary global state.
- Validate input at clear boundaries.
- Catch specific exceptions instead of using overly broad handlers.
- Provide useful error messages and log unexpected failures.
- Use
finallyor context managers for resource cleanup. - Reuse standard-library functionality instead of duplicating code.
- Protect executable code with
if __name__ == "__main__". - Write tests for normal cases, boundary cases, and failure cases.
- Use custom exceptions when application-specific errors need separate handling.
These practices make code easier to understand, test, extend, and recover from errors.
Explain the purpose of exception handling in Python. Describe the syntax and execution flow of a try and except block with a suitable example.
Exception handling allows a program to respond to runtime errors without terminating abruptly.
A basic structure is:
try:
number = int(input("Enter a number: "))
result = 10 / number
except ZeroDivisionError:
print("Division by zero is not allowed.")
except ValueError:
print("Please enter a valid integer.")- Statements that may produce an exception are placed inside the
tryblock. - If an exception occurs, Python searches for a matching
exceptblock. - The remaining statements in the
tryblock are skipped after the exception. - If no exception occurs, all
exceptblocks are skipped. - Handling errors improves program reliability and user experience.
Did this save you a night before the exam?
LPU Notes is free, and it stays free. Ads cover part of the server bill. The rest comes out of a student's own pocket: the domain, the storage, and keeping the site up through the weeks everyone needs it at once.
The payment button didn't load. An ad blocker or a filtered network is the usual reason. to try again.
Nothing here is ever locked, and nothing unlocks. Chip in only if it was worth it. What it pays for →