python 的内建属性__getattr__的妙用

__getattr__函数的作用: 如果属性查找在实例以及对应的类中(通过__dict__)失败, 那么会调用到类的__getattr__函数, 如果没有定义这个函数,那么抛出AttributeError异常。由此可见,__getattr__一定是作用于属性查找的最后一步。

下面是是openstack rpc中代码:

class _ContextWrapper(object):
    def __init__(self, original_context):
        self._original_context = original_context
    # __this is getattr value
    def __getattr__(self, name):
        return getattr(self._original_context, name)

    def cast(self, ctxt, method, **kwargs):
        try:
            self._original_context.cast(ctxt, method, **kwargs)
        except Exception as e:
            # TODO(kevinbenton): make catch specific to missing exchange once
            # bug/1705351 is resolved on the oslo.messaging side; if
            # oslo.messaging auto-creates the exchange, then just remove the
            # code completely
            LOG.debug("Ignored exception during cast: %e", e)

rpc 使用call方法的使用,使用的context类是 neutron.common.rpc._ContextWrapper,但是类中无call方法。

cctxt.call(context, 'funcname', function=function)

最后发现是__getattr__内部函数,查找了original_context(oslo_messaging.rpc.client._CallContext)中的call名称的方法,原生代码写的很晦涩。

下面把rpc client使用的rpc代码贴出来。

class BackingOffClient(oslo_messaging.RPCClient):
    """An oslo messaging RPC Client that implements a timeout backoff.

    This has all of the same interfaces as oslo_messaging.RPCClient but
    if the timeout parameter is not specified, the _BackingOffContextWrapper
    returned will track when call timeout exceptions occur and exponentially
    increase the timeout for the given call method.
    """
    def prepare(self, *args, **kwargs):
        ctx = super(BackingOffClient, self).prepare(*args, **kwargs)
        # don't back off contexts that explicitly set a timeout
        if 'timeout' in kwargs:
            return _ContextWrapper(ctx)
        return _BackingOffContextWrapper(ctx)

    @staticmethod
    def set_max_timeout(max_timeout):
        '''Set RPC timeout ceiling for all backing-off RPC clients.'''
        _BackingOffContextWrapper.set_max_timeout(max_timeout)


def get_client(target, version_cap=None, serializer=None):
    assert TRANSPORT is not None
    serializer = RequestContextSerializer(serializer)
    return BackingOffClient(TRANSPORT,
                            target,
                            version_cap=version_cap,
                            serializer=serializer)

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值