繁体   English   中英

Python Object 池设计模式的实现

[英]Python Implementation of the Object Pool Design Pattern

我需要一个Object Pool ,而不是自己实现它,我想我会四处寻找现成的和经过测试的 Python 库。

我发现很多其他人都在寻找,但没有得到很多直接的答案,所以我把它带到了 Stack Overflow。

在我的例子中,我有大量线程(使用threading模块),它们需要偶尔调用远程基于 SOAP 的服务器。 他们每个人都可以建立自己的服务器连接,但是设置套接字和完成身份验证过程非常昂贵(它受到服务器的限制),所以我想共享一个连接池,只在需要时创建更多连接。

如果要池的项目是工作子进程,我可能会选择multiprocessing.pool ,但它们不是。 如果它们是工作线程,我可能会选择这个实现,但它们不是。

如果它们是 MySQL 个连接,我可能会选择pysqlpool ,但它们不是。 类似地, SQLAlchemy 池已用完。

如果有一个线程,使用可变数量的连接/对象,我会考虑这个实现,但我需要它是线程安全的。

我知道我可以相当快地再次实现它,但鉴于有很多人在寻找它,我认为 Stack Overflow 上的规范答案会很好。

在我看来,根据您的描述,您需要的是一个连接池,而不是对象。 为了简单的线程安全,只需将可重用连接保存在Queue.Queue实例中,将其称为pool 当一个线程实例化一个连接包装对象时,该对象通过pool.get()获取它的连接pool.get()如果当前没有pool.get()连接,它会自动将它pool.get()等待,并在连接准备好时将它出队); 当对象使用其连接完成后,它会通过pool.put将其放回池中。

除了Queue.Queue已经为您提供的功能之外,这里几乎没有普遍需要的通用功能,因此没有模块提供它是众所周知或流行的也就不足为奇了——当一个模块有大约 6 行时,很难使其广泛传播全部功能代码(例如,调用用户提供的连接工厂以提前或及时填充队列直至达到某个最大数量——无论如何,这通常不是一个很大的附加值)。 “厚胶”,从标准库模块中厚厚地包裹底层功能而没有实质性的附加值,毕竟是架构上的减法;-)。

我有一个类似的问题,我必须说 Queue.Queue 非常好,但是有一个拼图的缺失部分。 以下类有助于确保获取的对象返回到池中。 包括示例。

我允许通过 2 种方式使用此类,即使用关键字或使用析构函数封装对象。 with 关键字是首选,但如果您由于某种原因不能/不想使用它(最常见的是需要来自多个队列的多个对象),至少您有一个选择。 如果您选择使用该方法,则有关不会调用析构函数的标准免责声明适用。

希望这可以帮助与 OP 和我自己有相同问题的人。

class qObj():
  _q = None
  o = None

  def __init__(self, dQ, autoGet = False):
      self._q = dQ

      if autoGet == True:
          self.o = self._q.get()

  def __enter__(self):
      if self.o == None:
          self.o = self._q.get()
          return self.o
      else:
          return self.o 

  def __exit__(self, type, value, traceback):
      if self.o != None:
          self._q.put(self.o)
          self.o = None

  def __del__(self):
      if self.o != None:
          self._q.put(self.o)
          self.o = None


if __name__ == "__main__":
  import Queue

  def testObj(Q):
      someObj = qObj(Q, True)

      print 'Inside func: {0}'.format(someObj.o)

  aQ = Queue.Queue()

  aQ.put("yam")

  with qObj(aQ) as obj:
      print "Inside with: {0}".format(obj)

  print 'Outside with: {0}'.format(aQ.get())

  aQ.put("sam")

  testObj(aQ)

  print 'Outside func: {0}'.format(aQ.get())

  '''
  Expected Output:
  Inside with: yam
  Outside with: yam
  Inside func: sam
  Outside func: sam
  '''

对于简单的用例,这里是基于列表的对象池模式的示例实现:

来源:

https://sourcemaking.com/design_patterns/object_pool

https://sourcemaking.com/design_patterns/object_pool/python/1

"""
Offer a significant performance boost; it is most effective in
situations where the cost of initializing a class instance is high, the
rate of instantiation of a class is high, and the number of
instantiations in use at any one time is low.
"""


class ReusablePool:
    """
    Manage Reusable objects for use by Client objects.
    """

    def __init__(self, size):
        self._reusables = [Reusable() for _ in range(size)]

    def acquire(self):
        return self._reusables.pop()

    def release(self, reusable):
        self._reusables.append(reusable)


class Reusable:
    """
    Collaborate with other objects for a limited amount of time, then
    they are no longer needed for that collaboration.
    """

    pass


def main():
    reusable_pool = ReusablePool(10)
    reusable = reusable_pool.acquire()
    reusable_pool.release(reusable)


if __name__ == "__main__":
    main()

您可以尝试我的开源 python object 池之一。

Pond 是 Python 的高性能对象池库,它具有较小的 memory 使用率和较高的借用命中率。

https://github.com/T-baby/pondpond

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM