MST

星途 面试题库

面试题:Python自定义异常与错误处理的最佳实践

假设你正在开发一个大型的Python项目,为了更好地管理错误与异常,需要设计一套自定义异常类体系。请阐述设计思路,包括如何继承内置异常类、如何合理命名异常类以及如何在不同模块间统一处理这些自定义异常。同时,给出一段复杂业务场景下的代码示例,展示自定义异常的抛出、捕获和处理过程。
22.5万 热度难度
编程语言Python

知识考点

AI 面试

面试题答案

一键面试

设计思路

  1. 继承内置异常类
    • 对于一般性的业务异常,可以继承Exception类。例如,如果项目中有与数据处理相关的异常,可创建一个DataProcessingError类继承自Exception
    • 对于更特定类型的异常,根据异常的性质选择更合适的内置异常类作为基类。比如,涉及输入验证的异常可继承ValueError,如果是与索引相关的业务异常可考虑继承IndexError。这样可以利用内置异常类的已有特性和行为,并且在捕获异常时能更精准地处理不同类型问题。
  2. 合理命名异常类
    • 异常类命名应清晰地反映异常发生的场景或原因。例如,在用户认证模块,若密码错误可命名为InvalidPasswordError;在文件读取模块,若文件格式不符合预期可命名为UnexpectedFileFormatError。使用驼峰命名法,使名称易于阅读和理解。
  3. 不同模块间统一处理自定义异常
    • 创建一个专门的异常处理模块,例如common_exceptions.py,在其中定义所有的自定义异常类。这样不同模块都可以从这个公共模块导入异常类,保证异常类的一致性。
    • 在每个模块中,捕获异常时尽量遵循统一的结构。可以在模块的入口函数处设置一个通用的异常捕获块,将异常处理逻辑集中起来。如果需要在模块内部不同函数中处理异常,也尽量保持处理方式的一致性,例如记录日志、返回特定错误码等。

代码示例

# common_exceptions.py
class OrderProcessingError(Exception):
    pass

class ProductNotFoundError(OrderProcessingError):
    pass

class InsufficientStockError(OrderProcessingError):
    pass


# inventory.py
class Inventory:
    def __init__(self):
        self.products = {'product1': 10, 'product2': 5}

    def check_stock(self, product, quantity):
        if product not in self.products:
            raise ProductNotFoundError(f"Product {product} not found in inventory.")
        if self.products[product] < quantity:
            raise InsufficientStockError(f"Insufficient stock for {product}. Available: {self.products[product]}")
        return True


# order.py
from common_exceptions import ProductNotFoundError, InsufficientStockError


def process_order(product, quantity, inventory):
    try:
        if inventory.check_stock(product, quantity):
            print(f"Processing order for {product} with quantity {quantity}")
            # 实际业务中这里会有扣减库存等操作
    except ProductNotFoundError as pnf:
        print(f"Error: {pnf}. Cannot process order.")
    except InsufficientStockError as ise:
        print(f"Error: {ise}. Please adjust quantity.")


# main.py
from inventory import Inventory
from order import process_order


if __name__ == "__main__":
    inventory = Inventory()
    process_order('product1', 15, inventory)
    process_order('product3', 5, inventory)

在上述代码中,首先在common_exceptions.py中定义了OrderProcessingError及其子类ProductNotFoundErrorInsufficientStockErrorinventory.py中的Inventory类用于检查库存并可能抛出异常。order.py中的process_order函数捕获并处理这些异常。main.py通过调用process_order函数模拟复杂业务场景下异常的抛出、捕获和处理过程。