1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
U
M±d° ã@sPdZddlmZGdd„deƒZGdd„deƒZGdd„dƒZGd    d
„d
ƒZd S) a8 SimplePooledDB - a very simple DB-API 2 database connection pool.
 
Implements a pool of threadsafe cached DB-API 2 connections
to a database which are transparently reused.
 
This should result in a speedup for persistent applications
such as the "Webware for Python" AppServer.
 
For more information on the DB-API 2, see:
    https://www.python.org/dev/peps/pep-0249/
For more information on Webware for Python, see:
    https://webwareforpython.github.io/w4py/
 
Measures are taken to make the pool of connections threadsafe
regardless of whether the DB-API 2 module used is threadsafe
on the connection level (threadsafety > 1) or not.  It must only
be threadsafe on the module level (threadsafety = 1).  If the
DB-API 2 module is threadsafe, the connections will be shared
between threads (keep this in mind if you use transactions).
 
Usage:
 
The idea behind SimplePooledDB is that it's completely transparent.
After you have established your connection pool, stating the
DB-API 2 module to be used, the number of connections
to be cached in the pool and the connection parameters, e.g.
 
    import pgdb  # import used DB-API 2 module
    from dbutils.simple_pooled_db import PooledDB
    dbpool = PooledDB(pgdb, 5, host=..., database=..., user=..., ...)
 
you can demand database connections from that pool,
 
    db = dbpool.connection()
 
and use them just as if they were ordinary DB-API 2 connections.
It's really just a proxy class.
 
db.close() will return the connection to the pool, it will not
actually close it.  This is so your existing code works nicely.
 
Ideas for improvement:
 
* Do not create the maximum number of connections on startup
already, but only a certain number and the rest on demand.
* Detect and transparently reset "bad" connections.
* Connections should have some sort of maximum usage limit
after which they should be automatically closed and reopened.
* Prefer or enforce thread-affinity for the connections,
allowing for both sharable and non-sharable connections.
 
Please note that these and other ideas have been already
implemented in in PooledDB, a more sophisticated version
of SimplePooledDB.  You might also consider using PersistentDB
instead for thread-affine persistent database connections.
SimplePooledDB may still serve as a very simple reference
and example implementation for developers.
 
 
Copyright, credits and license:
 
* Contributed as MiscUtils/DBPool for Webware for Python
  by Dan Green, December 2000
* Thread safety bug found by Tom Schwaller
* Fixes by Geoff Talvola (thread safety in _threadsafe_getConnection())
* Clean up by Chuck Esterbrook
* Fix unthreadsafe functions which were leaking, Jay Love
* Eli Green's webware-discuss comments were lifted for additional docs
* Clean-up and detailed commenting, rename and move to DBUtils
  by Christoph Zwerschke in September 2005
 
Licensed under the MIT license.
é)Ú __version__c@seZdZdZdS)Ú PooledDBErrorzGeneral PooledDB error.N©Ú__name__Ú
__module__Ú __qualname__Ú__doc__©r    r    úOd:\z\workplace\vscode\pyvenv\venv\Lib\site-packages\dbutils/simple_pooled_db.pyrNsrc@seZdZdZdS)ÚNotSupportedErrorz(DB-API module not supported by PooledDB.Nrr    r    r    r
r Rsr c@s0eZdZdZdd„Zdd„Zdd„Zdd    „Zd
S) ÚPooledDBConnectionz—A proxy class for pooled database connections.
 
    You don't normally deal with this class directly,
    but use PooledDB to get new connections.
    cCs||_||_dS©N)Ú_conÚ_pool)ÚselfÚpoolÚconr    r    r
Ú__init__]szPooledDBConnection.__init__cCs"|jdk    r|j |j¡d|_dS)zClose the pooled connection.N)rrÚreturnConnection©rr    r    r
Úcloseas
zPooledDBConnection.closecCs t|j|ƒSr )Úgetattrr)rÚnamer    r    r
Ú __getattr__iszPooledDBConnection.__getattr__cCs | ¡dSr )rrr    r    r
Ú__del__mszPooledDBConnection.__del__N)rrrrrrrrr    r    r    r
r Vs
r c@sLeZdZdZeZdd„Zdd„Zdd„Zdd    „Z    d
d „Z
d d „Z dd„Z dS)ÚPooledDBzA very simple database connection pool.
 
    After you have created the connection pool,
    you can get connections using getConnection().
    c    Osz
|j}Wntk
r"d}YnX|dkr6tdƒ‚n¨|dkr”zddlm}Wn tk
rnddlm}YnX||ƒ|_|j|_|j    |_
|j |_ nJ|dkrÖddl m}|ƒ|_d|_g|_|j|_|j|_
|j|_ ntdƒ‚t|ƒD]}| 
|j||Ž¡qædS)    a*Set up the database connection pool.
 
        dbapi: the DB-API 2 compliant module you want to use
        maxconnections: the number of connections cached in the pool
        args, kwargs: the parameters that shall be used to establish
            the database connections using connect()
        Néz8Database module does not support any level of threading.r)ÚQueue)éé)ÚLockz7Database module threading support cannot be determined.)Ú threadsafetyÚ    Exceptionr rÚ ImportErrorÚqueueÚ_queueÚ_unthreadsafe_get_connectionÚ
connectionÚ_unthreadsafe_add_connectionZ addConnectionÚ_unthreadsafe_return_connectionrÚ    threadingr Ú_lockÚ_nextConnectionÚ _connectionsÚ_threadsafe_get_connectionÚ_threadsafe_add_connectionÚ_threadsafe_return_connectionÚrangeÚconnect)    rZdbapiZmaxconnectionsÚargsÚkwargsr!rr Úir    r    r
rzs<
 
ÿ
 
 
ÿ zPooledDB.__init__cCst||j ¡ƒS)úGet a connection from the pool.)r r%Úgetrr    r    r
r&®sz%PooledDB._unthreadsafe_get_connectioncCs|j |¡dS©zAdd a connection to the pool.N)r%Úput©rrr    r    r
r(²sz%PooledDB._unthreadsafe_add_connectioncCs| |¡dS)aReturn a connection to the pool.
 
        In this case, the connections need to be put
        back into the queue after they have been used.
        This is done automatically when the connection is closed
        and should never be called explicitly outside of this module.
        N)r(r:r    r    r
r)¶sz(PooledDB._unthreadsafe_return_connectioncCsZ|j ¡z>|j}t||j|ƒ}|d7}|t|jƒkr<d}||_|W¢S|j ¡XdS)r6rrN)r+ÚacquireÚreleaser,r r-Úlen)rÚnextrr    r    r
r.Ås
z#PooledDB._threadsafe_get_connectioncCs|j |¡dSr8)r-Úappendr:r    r    r
r/Ósz#PooledDB._threadsafe_add_connectioncCsdS)zšReturn a connection to the pool.
 
        In this case, the connections always stay in the pool,
        so there is no need to do anything here.
        Nr    r:r    r    r
r0×sz&PooledDB._threadsafe_return_connectionN) rrrrrÚversionrr&r(r)r.r/r0r    r    r    r
rqs4rN)rÚrr"rr r rr    r    r    r
Ú<module>s
J