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

Python中inspect.getmembers处理抛异常@property方法的异常行为

Python inspect.getmembers触发@property直接抛异常的问题

问题复现

import inspect

class SomeClass:
    def __init__(self):
        inspect.getmembers(self, predicate=inspect.ismethod)

    def this_is_okay(self):
        raise Exception('an error that may be thrown')

    @property
    def this_is_not_okay(self):
        raise Exception('an error that may be thrown')

    @property
    def but_this_is_okay(self):
        if True:
            raise Exception('an error that may be thrown')

创建SomeClass实例时,会触发this_is_not_okay中抛出的异常,但普通方法不会(注:but_this_is_okay的getter被调用时实际也会抛异常,核心问题是@property的getter会被inspect.getmembers触发)。

原因

inspect.getmembers(self, predicate=inspect.ismethod)的执行逻辑是:

  1. 先遍历并获取实例的所有属性值,包括@property定义的属性——获取这类属性值会直接调用其getter函数。
  2. 再用inspect.ismethod过滤结果,只保留方法对象。
  • 普通方法:获取到的是方法对象本身,不会执行方法体,所以即使方法内抛异常也不会触发。
  • @property属性:获取属性值时会直接执行getter,若getter在顶层直接抛异常,就会立即触发错误。

另外,inspect.getmembers默认按字母顺序返回结果,本身也不符合你「按类定义顺序获取方法」的需求。

解决方法

针对你按类定义顺序获取实例可调用方法的核心需求,推荐以下方案:

方案1:遍历类__dict__按定义顺序筛选(推荐)

Python 3.7+中,类的__dict__会保留成员的定义顺序,直接遍历类的成员,筛选出函数并绑定为实例方法:

import inspect

class SomeClass:
    def __init__(self):
        # 按定义顺序收集实例方法
        instance_methods = []
        # 遍历类的成员而非实例,避免触发property getter
        for name, member in self.__class__.__dict__.items():
            # 筛选类中定义的函数(未绑定方法)
            if inspect.isfunction(member):
                # 绑定为实例方法
                bound_method = getattr(self, name)
                instance_methods.append(bound_method)
        
        # 验证结果:按定义顺序输出方法名
        print([m.__name__ for m in instance_methods])
        # 输出:['__init__', 'this_is_okay']

    def this_is_okay(self):
        raise Exception('an error that may be thrown')

    @property
    def this_is_not_okay(self):
        raise Exception('an error that may be thrown')

    @property
    def but_this_is_okay(self):
        if True:
            raise Exception('an error that may be thrown')

这种方式完全不会触发@property的getter,同时严格保留方法的定义顺序。

方案2:自定义过滤规则避免触发property(不推荐,无法保留顺序)

如果一定要使用inspect.getmembers,可以先判断成员是否为property,跳过它们,但结果会按字母排序:

import inspect

def filter_instance_methods(obj):
    # 先排除property对象,避免触发getter
    if isinstance(obj, property):
        return False
    return inspect.ismethod(obj)

class SomeClass:
    def __init__(self):
        members = inspect.getmembers(self, predicate=filter_instance_methods)
        # 输出按字母序排列的方法名
        print([name for name, _ in members])
        # 输出:['__init__', 'this_is_okay']

    # ... 其他方法同上

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 11:46:06