Python Implementation of the Object Pool Design Pattern

Tags: , ,



I need an Object Pool, and rather than implement it myself, I thought I would look around for a ready-made and tested Python library.

What I found was plenty of other people looking, but not getting many straight answers, so I have brought it over here to Stack Overflow.

In my case, I have a large number of threads (using the threading module), which need to occasionally call a remote SOAP-based server. They could each establish their own connection to the server, but setting up a socket and completing the authentication process is expensive (it is throttled by the server), so I want to share a pool of connections, creating more only as needed.

If the items to pool were worker subprocesses, I might have chosen multiprocessing.pool, but they are not. If they were worker threads, I might have chosen this implementation, but they are not.

If they were MySQL connections, I might have chosen pysqlpool, but they are not. Similarly the SQLAlchemy Pool is out.

If there was one thread, using a variable number of connections/objects, I would consider this implementation, but I need it to be thread-safe.

I know I could implement this again fairly quickly, but given there are many people looking for it, I thought a canonical answer on Stack Overflow would be nice.

Answer

It seems to me, from your description, that what you need is a pool of connections, not of objects. For simple thread-safety, just keep the reusable connections in a Queue.Queue instance, call it pool. When a thread instantiates a connection-wrapping object, the object gets its connection via pool.get() (which automaticaly enqueues it to wait if there are no connections currently availabe and dequeues it when a connection’s ready for it); when the object’s done using its connection, it puts it back in the pool via pool.put.

There’s so little universally-required, general-purpose functionality in this, beyond what Queue.Queue already gives you, that it’s not surprising no module providing it is well known or popular — hard to make a module widespread when it has about 6 lines of functional code in all (e.g. to call a user-supplied connection factory to populate the queue either in advance or just-in-time up to some maximum number — not a big added value generally, anyway). “Thick glue”, thickly wrapping the underlying functionality from a standard library module without substantial added value, is an architectural minus, after all;-).



Source: stackoverflow