4. Errors and ExceptionsAn error is a defect or condition that prevents a program from producing the intended result. Syntax errors prevent code from being parsed. Runtime errors occur while code executes. Logical errors allow execution but produce incorrect results. An exception is an object representing an abnormal condition during execution. For example, opening a missing file raises 4.1 Handling Exceptionsfrom pathlib import Path
try:
with Path("data/sales.csv").open(encoding="utf-8") as file:
first_line = file.readline()
except FileNotFoundError:
print("The sales file was not found.")
except PermissionError:
print("The application does not have permission to read the file.")Specific exceptions should normally be caught before broader exceptions. This preserves useful information and avoids hiding unrelated programming defects. A complete structure is: try:
value = int(user_text)
except ValueError:
print("Enter a whole number.")
else:
print(f"Accepted value: {value}")
finally:
print("Input attempt completed.")The 4.2 Raising Exceptions DeliberatelyA function should reject invalid data rather than silently returning a misleading result. def convert_amount(text):
try:
amount = float(text)
except ValueError as error:
raise ValueError("Amount must be numeric") from error
if amount < 0:
raise ValueError("Amount cannot be negative")
return amountException chaining, using Do not use a bare 5. Validation and Defensive AnalyticsFile access and data validation solve different problems. A file may exist and be readable while containing malformed or semantically impossible data. Validation should address:
For example, a transaction record may satisfy the type requirement that A useful design separates file input, validation, transformation, and analysis. This separation makes tests more focused and allows the analysis function to operate on clean Python objects rather than file-specific details. 6. Object-Oriented FoundationsObject-oriented programming (OOP) organises software around objects that combine data and behaviour. A class is a blueprint; an object, or instance, is a concrete value created from that class. class Sale:
def __init__(self, order_id, amount, region):
self.order_id = order_id
self.amount = amount
self.region = region
def is_large(self, threshold):
return self.amount >= threshold
sale = Sale("A104", 2500.0, "East")
print(sale.region)
print(sale.is_large(2000))
6.1 Encapsulation and InvariantsEncapsulation groups related data and operations and controls how state is changed. Python does not enforce private attributes in the same way as some languages, but a leading underscore communicates that an attribute is intended for internal use. class InventoryItem:
def __init__(self, sku, quantity):
self.sku = sku
self._quantity = 0
self.quantity = quantity
@property
def quantity(self):
return self._quantity
@quantity.setter
def quantity(self, value):
if not isinstance(value, int) or value < 0:
raise ValueError("Quantity must be a non-negative integer")
self._quantity = valueThe rule that quantity cannot be negative is an invariant: a condition that should remain true for every valid object. Centralising the rule prevents different parts of an application from applying inconsistent checks. 6.2 Class and Static MethodsAn instance method receives class Sale:
tax_rate = 0.2
def __init__(self, amount):
self.amount = amount
@classmethod
def from_text(cls, text):
return cls(float(text))
@staticmethod
def valid_amount(amount):
return amount >= 0
6.3 Composition Rather Than Unnecessary InheritanceComposition means building a class from objects of other classes. An Inheritance expresses an “is a” relationship, such as 7. An Integrated Analytics ExampleThe following illustrative design reads CSV records, converts them into import csv
from pathlib import Path
class Sale:
def __init__(self, order_id, amount, region):
if not order_id:
raise ValueError("Order ID is required")
if amount < 0:
raise ValueError("Amount cannot be negative")
self.order_id = order_id
self.amount = amount
self.region = region
@classmethod
def from_row(cls, row):
return cls(
row["order_id"].strip(),
float(row["amount"]),
row["region"].strip()
)
class SalesRepository:
def __init__(self, path):
self.path = Path(path)
def load(self):
records = []
with self.path.open(newline="", encoding="utf-8") as file:
reader = csv.DictReader(file)
required = {"order_id", "amount", "region"}
if not required.issubset(reader.fieldnames or set()):
raise ValueError("CSV is missing required columns")
for row_number, row in enumerate(reader, start=2):
try:
records.append(Sale.from_row(row))
except (KeyError, TypeError, ValueError) as error:
raise ValueError(
f"Invalid record on row {row_number}"
) from error
return records
class SalesSummary:
def total_revenue(self, sales):
return sum(sale.amount for sale in sales)
repository = SalesRepository("data/sales.csv")
try:
sales = repository.load()
summary = SalesSummary()
print(summary.total_revenue(sales))
except (FileNotFoundError, PermissionError, ValueError) as error:
print(f"Could not process sales data: {error}")This design demonstrates several professional practices: paths are represented by 8. Case Study: Regional Sales ReportingIllustrative case. A retail company receives a daily CSV export from four regional branches. The existing script manually splits lines, assumes every amount is valid, and writes reports into a path that works only on the developer’s computer. Occasionally, one malformed row causes the entire report to fail without a useful explanation. ProblemThe company needs a repeatable process that is portable across computers, identifies invalid records, and produces trustworthy regional totals. AnalysisManual string splitting can misinterpret quoted commas. Hard-coded paths reduce portability. Processing all values as strings can produce incorrect arithmetic, while catching every exception can conceal programming defects. The application needs explicit format handling, validation, and controlled error reporting. Approach and SolutionThe redesigned process uses OutcomeThe process becomes portable and auditable. Analysts can distinguish a missing input file from a malformed row. The summary calculation operates on validated objects, reducing the risk that formatting details contaminate business logic. Learning PointsReliable analytics depends on more than a correct formula. Input contracts, validation rules, error handling, and resource management determine whether results can be trusted. Classes are useful here because a 9. Limitations, Governance and Best PracticesObject-oriented design can improve maintainability, but it also introduces abstraction, indirection, and additional code. A small script may be clearer with functions and dictionaries. Classes should be introduced when they clarify a domain concept, protect invariants, manage related behaviour, or support testing and reuse. File-based workflows also have limitations. CSV lacks strong typing and schema enforcement. Large files may exceed available memory if loaded entirely. Concurrent processes can overwrite outputs, and partial writes can leave incomplete reports. For critical systems, use temporary files followed by an atomic replacement strategy, maintain backups, and record processing metadata. Security and governance are essential. Do not execute code or deserialize untrusted content merely because it arrives in a file. Restrict file permissions, validate paths, protect confidential customer data, and avoid placing personal data in logs. Retention, access control, auditability, and applicable privacy law should shape the design of analytics pipelines. Best practices include:
Chapter SummaryFiles provide persistent storage for analytics inputs, outputs, configurations, and logs. Python’s context managers ensure that resources are closed reliably. Object-oriented programming combines state and behaviour in objects. Classes are valuable when they represent domain concepts, enforce invariants, or separate responsibilities. Instance methods operate on objects, class methods provide class-aware alternatives such as constructors, and static methods provide related utilities. Composition is often more flexible than unnecessary inheritance. In analytics applications, a design that separates file access, domain validation, and analysis is more testable and maintainable than a single large procedure. Key TermsFile: A persistent named storage resource. Path: A representation of a file or directory location. Encoding: A rule for representing characters as bytes. CSV: A text format for tabular, delimiter-separated data. JSON: A structured text format for objects, arrays, and primitive values. Context manager: A construct that manages setup and cleanup around a block. Exception: An object representing an abnormal execution condition. Validation: Checking that data satisfies structural and business requirements.
Class: A blueprint defining data and behaviour for objects. Object: A concrete instance of a class. Attribute: Data associated with an object or class. Method: A function defined within a class. Encapsulation: Combining data and operations while controlling access to state. Invariant: A condition that must remain true for a valid object. Composition: Constructing an object from other collaborating objects. Inheritance: Creating a specialised class from a parent class. Repository: A component responsible for obtaining or storing domain data. Serialization: Representing data in a form suitable for storage or transmission. Review QuestionsShort Answer Questions
Long Answer Questions
Analytical / Application Questions
Multiple Choice Questions with AnswersQuestion 1Which file mode appends data to an existing text file? A. "r" B. "w" C. "a" D. "x" Correct Answer: C. "a" Question 2Which Python tool provides a platform-aware representation of file paths? A. B. C. D. Correct Answer: A. Question 3What type is normally returned for a CSV field read by A. Integer B. String C. Boolean D. Date Correct Answer: B. String Question 4Which exception commonly indicates that a requested file does not exist? A. B. C. D. Correct Answer: C. Question 5What is the main purpose of a A. To run cleanup code regardless of whether an exception occurs B. To define a new class C. To convert CSV values to JSON D. To suppress every programming error Correct Answer: A. To run cleanup code regardless of whether an exception occurs Question 6In a class method, which name conventionally refers to the class itself? A. B. C. D. Correct Answer: D. Question 7Which concept describes a rule that a valid object must continue to satisfy? A. Delimiter B. Invariant C. Encoding D. Serialization Correct Answer: B. Invariant Question 8Why should a program avoid a bare A. It cannot catch any exception B. It catches only file errors C. It can conceal unrelated and serious conditions D. It automatically closes all files Correct Answer: C. It can conceal unrelated and serious conditions Question 9Which design separates file access from business analysis most directly? A. Putting all operations in one long function B. Using a repository component for data access C. Ignoring malformed records silently D. Hard-coding every output path Correct Answer: B. Using a repository component for data access Question 10Which statement about JSON is correct? A. It automatically preserves every Python type B. It is limited to flat tables C. It supports nested objects and arrays D. It cannot represent Boolean values Correct Answer: C. It supports nested objects and arrays
Python Programming for Business Analytics
|
Chapter 5 of 14 |