Возможно, это не лучший дизайн, но вы можете предоставить ссылку на блокировку для тела оператора with
:
@contextmanager
def acquire_lock(self, path, identifier):
lock = zk.Lock(path, identifier)
try:
retry = KazooRetry()
retry(lock.acquire)
yield lock
finally:
lock.release()
with acquire_lock('/some_op/') as lock:
...
if necessary:
lock.release()
...
В зависимости от вашего вопроса (я не знаком с Kazoo), вы можете определить my_listener
в менеджере контекста, где он может закрываться через блокировку.
@contextmanager
def acquire_lock(self, path, identifier):
lock = zk.Lock(path, identifier)
def my_listener(state):
if state == KazooState.LOST:
lock.release()
elif state == KazooState.SUSPENDED:
...
try:
retry = KazooRetry()
# etc
Вашему контексту может потребоваться выдать слушателя или зарегистрировать его (или что бы вы ни делали со слушателями), но что бы вы ни делали с ним, он получит доступ к блокировке, созданной вами в диспетчере контекста.