python循环顶帖_设计Python数据库连接池1-对象的循环引用问题
在Python中如果對(duì)象定義了__del__方法的話,在對(duì)象的引用記數(shù)為0時(shí)會(huì)自動(dòng)調(diào)用__del__方法(很象c++中的析構(gòu)函數(shù)),但如果A對(duì)象引用B對(duì)象,B對(duì)象又引用A對(duì)象,就形成循環(huán)引用,此時(shí)A,B對(duì)象引用次數(shù)都為1。python就無(wú)法正常調(diào)用__del__方法,原計(jì)劃在__del__方法里釋放的資源自然也就無(wú)法釋放。
一個(gè)連接池?fù)碛卸鄠€(gè)連接,而每個(gè)連接又擁有這個(gè)連接池的實(shí)例(一個(gè)叫pool的屬性)。這樣就產(chǎn)生了剛剛說(shuō)的哪個(gè)問(wèn)題。我想到的辦法就是在每次從池中獲取連接的時(shí)候?qū)⑦B接的pool設(shè)置為當(dāng)前實(shí)例,然后在歸還這個(gè)連接的時(shí)候再將其設(shè)置為None,并且要在這個(gè)連接對(duì)象的__del__方法中將pool屬性設(shè)置為None。具體看代碼吧。(目前只實(shí)現(xiàn)了SQLite3的)
'''
Created on 2009-4-17
@author: phyeas
'''
import time
from queue import Queue
class PoolException(Exception):
pass
class Pool(object):
'''一個(gè)數(shù)據(jù)庫(kù)連接池'''
def __init__(self, maxActive=5, maxWait=None, init_size=0, db_type="SQLite3", **config):
self.__freeConns = Queue(maxActive)
self.maxWait = maxWait
self.db_type = db_type
self.config = config
if init_size > maxActive:
init_size = maxActive
for i in range(init_size):
self.free(self._create_conn())
def __del__(self):
print("__del__ Pool..")
self.release()
def release(self):
'''釋放資源,關(guān)閉池中的所有連接'''
print("release Pool..")
while self.__freeConns and not self.__freeConns.empty():
con = self.get()
con.release()
self.__freeConns = None
def _create_conn(self):
'''創(chuàng)建連接 '''
if self.db_type in dbcs:
return dbcs[self.db_type](**self.config);
def get(self, timeout=None):
'''獲取一個(gè)連接
@param timeout:超時(shí)時(shí)間
'''
if timeout is None:
timeout = self.maxWait
conn = None
if self.__freeConns.empty():#如果容器是空的,直接創(chuàng)建一個(gè)連接
conn = self._create_conn()
else:
conn = self.__freeConns.get(timeout=timeout)
conn.pool = self
return conn
def free(self, conn):
'''將一個(gè)連接放回池中
@param conn: 連接對(duì)象
'''
conn.pool = None
if(self.__freeConns.full()):#如果當(dāng)前連接池已滿(mǎn),直接關(guān)閉連接
conn.release()
return
self.__freeConns.put_nowait(conn)
from abc import ABCMeta, abstractmethod
class PoolingConnection(object, metaclass=ABCMeta):
def __init__(self, **config):
self.conn = None
self.config = config
self.pool = None
def __del__(self):
self.release()
def __enter__(self):
pass
def __exit__(self, exc_type, exc_value, traceback):
self.close()
def release(self):
print("release PoolingConnection..")
if(self.conn is not None):
self.conn.close()
self.conn = None
self.pool = None
def close(self):
if self.pool is None:
raise PoolException("連接已關(guān)閉")
self.pool.free(self)
def __getattr__(self, val):
if self.conn is None and self.pool is not None:
self.conn = self._create_conn(**self.config)
if self.conn is None:
raise PoolException("無(wú)法創(chuàng)建數(shù)據(jù)庫(kù)連接 或連接已關(guān)閉")
return getattr(self.conn, val)
@abstractmethod
def _create_conn(self, **config):
pass
class SQLit3PoolConnection(PoolingConnection):
def _create_conn(self, **config):
import sqlite3
return sqlite3.connect(**config)
dbcs = {"SQLite3":SQLit3PoolConnection}
pool = Pool(database="F:\\test\\a")
def test():
conn = pool.get()
with conn:
for a in conn.execute("SELECT * FROM A"):
print(a)
if __name__ == "__main__":
test()
以上代碼在python3.0中測(cè)試通過(guò)……
總結(jié)
以上是生活随笔為你收集整理的python循环顶帖_设计Python数据库连接池1-对象的循环引用问题的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: u-boot-2012-07 for t
- 下一篇: 实例64:python