You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python抛出异常并记录日志时如何减少重复样板代码

解决方案

以下三种方案按适用场景从简单到复杂排序:

方案1:本地变量复用(适配少量零散校验场景)

直接将重复的错误信息定义为本地变量,两处逻辑共用同一个变量即可,无需调整现有代码结构,改造成本最低。

@start_date.setter
def start_date(self, val: dt.datetime):
    if not isinstance(val, dt.datetime):
        # 错误信息统一定义,修改只需调整一处
        err_msg = f'Expecting datetime as start date, got {type(val)} instead.'
        # 补充exc_info=True输出调用栈,替换原不合理的logger.exception使用
        logger.error(err_msg, exc_info=True)
        raise TypeError(err_msg)
    self.__start_date = val

方案2:封装通用校验函数(适配多位置复用同类型校验)

如果项目中多处需要做类型校验、日志上报、异常抛出的逻辑,可以把这部分统一封装为工具函数,彻底避免重复的判断代码。

def validate_type(value, expected_type, prop_name, logger):
    if not isinstance(value, expected_type):
        err_msg = f'Expecting {expected_type.__name__} as {prop_name}, got {type(value).__name__} instead.'
        logger.error(err_msg, exc_info=True)
        raise TypeError(err_msg)

# setter中直接调用即可
@start_date.setter
def start_date(self, val: dt.datetime):
    validate_type(val, dt.datetime, "start date", logger)
    self.__start_date = val

后续如果要新增其他属性的类型校验,只需要一行调用即可,不需要重复写判断、日志、抛异常的逻辑。

方案3:自定义描述符(适配类存在大量需校验属性的场景)

如果你的类有多个属性都需要做类似的类型校验,可以自定义描述符封装完整的属性存取逻辑,连@property的重复定义都可以省去,一劳永逸。

class TypedProperty:
    def __init__(self, expected_type):
        self.expected_type = expected_type
        self.attr_name = None

    # 自动获取绑定的属性名
    def __set_name__(self, owner, name):
        self.attr_name = name

    def __get__(self, instance, owner):
        if instance is None:
            return self
        return instance.__dict__.get(f"_{self.attr_name}")

    def __set__(self, instance, value):
        if not isinstance(value, self.expected_type):
            err_msg = f'Expecting {self.expected_type.__name__} as {self.attr_name}, got {type(value).__name__} instead.'
            logger.error(err_msg, exc_info=True)
            raise TypeError(err_msg)
        instance.__dict__[f"_{self.attr_name}"] = value

# 类定义直接使用描述符,不需要额外写getter、setter
@dataclass
class Foo:
    start_date: dt.datetime = TypedProperty(dt.datetime)
    # 新增其他需要校验的属性只需要一行定义
    # end_date: dt.datetime = TypedProperty(dt.datetime)

如果后续需要扩展校验规则,比如增加非空校验、范围校验等,只需要修改描述符的__set__方法即可,所有用到的属性会自动生效。

内容的提问来源于stack exchange,提问作者NotAName

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 05:57:03