Я ищу общий и простой способ синхронизации методов класса 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/ и использовать блокирующие блокировки для каждого доступа. Я предпочел бы третий вариант. Меня просто беспокоит, что я не нашел для этого рецепта. Есть что-то с этим решением или есть лучший?синхронизировать доступ к объекту python
EDIT2: Последний вариант выглядит следующий фрагмент и был протестирован с codetidy.com/5911/. Тест не является доказательством того, что он работает, просто световая индикация. Поскольку это не мое ежедневное кодирование, это поможет, если кто-то более опытный может проверить, есть ли какие-либо ошибки.
#!/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)
EDIT3: Я пошел с SynchronizeProxy, и это, кажется, работает до сих пор. Поскольку это решение, ближе всего к тому, что мне нужно, я буду выбирать свой ответ в виде раствора
Можете ли вы рассказать о прокси-вызовах класса с очередью и о том, как это лучше предлагаемых решений? – phobic
Я немного адаптировал свой ответ. Надеюсь, поможет. – pypat