同步对python对象的访问 [英] synchronize access to python object

查看:24
本文介绍了同步对python对象的访问的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在寻找一种通用且简单的方法来同步本身不使用异步调用的 python 类的方法.我想到了一些可能性:一、在类本身的所有方法上使用装饰器:http://code.activestate.com/recipes/577105-synchronization-decorator-for-class-methods/.但我不希望更改类,因此其次,使用包装器或子类同步访问所有子类/核心方法.我想也许有一种通用的方法来同步对 python 对象的访问,这样你就不会意外地错过层次结构中超类的方法(特别是如果稍后更改它).因此,第三,您可能可以使用类似于以下内容的通用代理: http://code.activestate.com/recipes/366254-generic-proxy-object-with-beforeafter-method-hooks/并为每次访问使用可重入锁.我更喜欢第三种选择.只是让我感到烦恼,我没有找到这个食谱.这个解决方案有什么问题还是有更好的解决方案?

I am looking for a general and simple way to synchronize the methods of a python class that does not use asynchronous calls by itself. Some possibilities come to my mind: First, the use of decorators on all methods of the class itself: http://code.activestate.com/recipes/577105-synchronization-decorator-for-class-methods/. But I do not wish to change the class, so secondly, the use of a wrapper or a subclass synchronizing access to all subclass/core methods. I thought maybe, there is a generic way to synchronize access to a python object so that you do not accidentally miss a method from a superclass in the hierarchy (especially if it is changed later on). So, thirdly, you can probably use a generic proxy similar to: http://code.activestate.com/recipes/366254-generic-proxy-object-with-beforeafter-method-hooks/ and use reentrant locks for each access. I would prefer the third option. It just bugs me that I did not find a recipe for this. Is there something off with this solution or is there a better one?

最后一个选项类似于以下代码段,并使用 codetidy.com/5911/进行了测试.该测试不是证明它有效,只是一个指示灯.由于这不是我的日常编码,如果有经验的人可以检查一下是否有任何错误,这会有所帮助.

The last option looks like the following snippet and was tested with codetidy.com/5911/ . The test is not a prove that it works, just a light indication. Since this is not my everyday coding, it would help if someone more experienced could check to see if there are any bugs.

#!/usr/bin/env python
import types
from pprint import pformat
from threading import RLock

class SynchronizeMethodWrapper:
    """
    Wrapper object for a method to be called.
    """
    def __init__( self, obj, func, name, rlock ):
        self.obj, self.func, self.name = obj, func, name
        self.rlock = rlock
        assert obj is not None
        assert func is not None
        assert name is not None

    def __call__( self, *args, **kwds ):
        """
        This method gets called before a method is called to sync access to the core object.
        """
        with self.rlock:
            rval = self.func(*args, **kwds)
            return rval


class SynchronizeProxy(object):
    """
    Proxy object that synchronizes access to a core object methods and attributes that don't start with _.
    """
    def __init__( self, core ):
        self._obj = core
        self.rlock = RLock()

    def __getattribute__( self, name ):
        """
        Return a proxy wrapper object if this is a method call.
        """
        if name.startswith('_'):
            return object.__getattribute__(self, name)
        else:
            att = getattr(self._obj, name)
            if type(att) is types.MethodType:
                return SynchronizeMethodWrapper(self, att, name, object.__getattribute__(self, "rlock"))
            else:
                return att

    def __setitem__( self, key, value ):
        """
        Delegate [] syntax.
        """
        name = '__setitem__'
        with self.rlock:
            att = getattr(self._obj, name)
            pmeth = SynchronizeMethodWrapper(self, att, name, self.rlock)
            pmeth(key, value)

我使用了 SynchronizeProxy,到目前为止它似乎工作正常.由于这个解决方案最接近我的需要,我将选择我的答案作为解决方案

I went with the SynchronizeProxy, and it seems to work so far. Since this solution comes closest to what I need, I will select my answer as a solution

推荐答案

我使用了 SynchronizeProxy,到目前为止它似乎工作正常.由于此解决方案最接近我的需要,因此我将选择我的答案作为解决方案.如果我遇到任何问题,我会更新此答案.

I went with the SynchronizeProxy, and it seems to work so far. Since this solution comes closest to what I need, I will select my answer as a solution. If I experience any problems, I will update this answer.

#!/usr/bin/env python
import types
from pprint import pformat
from threading import RLock

class SynchronizeMethodWrapper:
    """
    Wrapper object for a method to be called.
    """
    def __init__( self, obj, func, name, rlock ):
        self.obj, self.func, self.name = obj, func, name
        self.rlock = rlock
        assert obj is not None
        assert func is not None
        assert name is not None

    def __call__( self, *args, **kwds ):
        """
        This method gets called before a method is called to sync access to the core object.
        """
        with self.rlock:
            rval = self.func(*args, **kwds)
            return rval


class SynchronizeProxy(object):
    """
    Proxy object that synchronizes access to a core object methods and attributes that don't start with _.
    """
    def __init__( self, core ):
        self._obj = core
        self.rlock = RLock()

    def __getattribute__( self, name ):
        """
        Return a proxy wrapper object if this is a method call.
        """
        if name.startswith('_'):
            return object.__getattribute__(self, name)
        else:
            att = getattr(self._obj, name)
            if type(att) is types.MethodType:
                return SynchronizeMethodWrapper(self, att, name, object.__getattribute__(self, "rlock"))
            else:
                return att

    def __setitem__( self, key, value ):
        """
        Delegate [] syntax.
        """
        name = '__setitem__'
        with self.rlock:
            att = getattr(self._obj, name)
            pmeth = SynchronizeMethodWrapper(self, att, name, self.rlock)
            pmeth(key, value)

这篇关于同步对python对象的访问的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆