0

我正在使用 python 2.7(迁移尚未完成)并尝试构建一个聚合类(Cluster),它提供与其单个项目(节点)相同的上下文管理器功能(保留)。理想情况下,我希望在不重构包含对象节点的上下文管理器功能的情况下做到这一点。如果它有单独的 enter() 和 exit() 方法,也许我会直接在 Cluster.reserved() 上下文管理器函数中调用它们。但我认为可能有更优雅的方式来做到这一点。我用 ExitStack 尝试了以下代码:

from contextlib import contextmanager
from contextlib2 import ExitStack

class Node:
    def __init__(self, id):
        self._id = id

    @contextmanager
    def reserved(self):
        print("Node {} reserved".format(self._id))
        try:
            yield
        except:
            print("Exception while handling node")
        finally:
            print("Node released")

    def reserve(self):
        print("Node {} reserved".format(self._id))

    def release(self):
            print("Node {} released".format(self._id))

class Cluster:
    def __init__(self, id):
        self._id = id
        self._nodes = [Node(1), Node(2), Node(3), Node(4)]

    @contextmanager
    def reserved(self):
        with ExitStack() as cm:
            cm.enter_context(node.reserved() for node in self._nodes)
            print("Cluster {} reserved".format(self._id))
            try:
                yield
            except:
                print("Exception while handling cluster")
            finally:
                print("Cluster released")
    @contextmanager
    def reserved2(self):
        with ExitStack() as cm:
            for node in self._nodes:
                reserve = node.reserve()
                cm.callback(node.release(), reserve)

            print("Cluster {} reserved".format(self._id))
            try:
                yield
            except:
                print("Exception while handling cluster")
            finally:
                print("Cluster released")

node = Node(10)
with node.reserved():
    print('Node {} handled'.format(node._id))


cluster = Cluster(10)
with cluster.reserved2():
    print('Cluster {} handled'.format(cluster._id))

第一个函数 reserved() 返回

AttributeError: type object 'generator' has no attribute '__exit__'

而第二个在保留所有节点后并没有真正产生。想知道处理这个问题的正确方法是什么......

4

1 回答 1

0
cm.enter_context(node.reserved() for node in self._nodes)

那个代码不对。我应该正确使用列表理解将 contextmanager 对象正确传递给 enter_context

于 2020-07-01T08:46:23.557 回答