对象池设计模式的Python实现

时间:2009-10-03 15:55:44

标签: python design-patterns data-structures

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

我发现很多其他人looking,但没有得到很多直接答案,所以我把它带到Stack Overflow。

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

如果要汇总的项目是工作人员子流程,我可能选择multiprocessing.pool,但事实并非如此。如果它们是工作线程,我可能选择了this implementation,但它们不是。{/ p>

如果他们是MySQL连接,我可能选择pysqlpool,但他们不是。{同样地,SQLAlchemy Pool已经出局。

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

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

3 个答案:

答案 0 :(得分:24)

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

除了Queue.Queue已经提供给你的东西之外,这里几乎没有普遍要求的通用功能,没有提供它的模块是众所周知的或流行的并不奇怪 - 当模块很难普及时它总共有大约6行功能代码(例如,调用用户提供的连接工厂以提前填充队列或准时填充到某个最大数量 - 通常不是一个很大的附加值)。 “厚胶”,从标准库模块中厚厚地包裹底层功能而没有实质性附加值,毕竟是体系结构减去; - )。

答案 1 :(得分:4)

我有一个类似的问题,我必须说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
  '''

答案 2 :(得分:0)

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

来源:

https://sourcemaking.com/design_patterns/object_pool

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


    foreach (var item in body.Items)
    {
        WriteItemPropertiesThatHaveValues(item);
    }


    void WriteItemPropertiesThatHaveValues<T>(T item)
    {
        foreach (PropertyInfo pi in typeof(Item).GetProperties())
        {
            WriteItemPropertyThatHasValue(item, pi);
        }
        Console.WriteLine();
    }

    void WriteItemPropertyThatHasValue<T>(T item, PropertyInfo pi)
    {
        T defaultTValue = default;
        var itemValue = pi.GetValue(item);

        if (!(itemValue?.Equals(defaultTValue) ?? true))
            Console.WriteLine($"\t{pi.Name} => { itemValue }");
    }