python循环顶帖_设计Python数据库连接池1-对象的循环引用问题

在Python中如果对象定义了__del__方法的话,在对象的引用记数为0时会自动调用__del__方法(很象c++中的析构函数),但如果A对象引用B对象,B对象又引用A对象,就形成循环引用,此时A,B对象引用次数都为1。python就无法正常调用__del__方法,原计划在__del__方法里释放的资源自然也就无法释放。

一个连接池拥有多个连接,而每个连接又拥有这个连接池的实例(一个叫pool的属性)。这样就产生了刚刚说的哪个问题。我想到的办法就是在每次从池中获取连接的时候将连接的pool设置为当前实例,然后在归还这个连接的时候再将其设置为None,并且要在这个连接对象的__del__方法中将pool属性设置为None。具体看代码吧。(目前只实现了SQLite3的)

'''

Created on 2009-4-17

@author: phyeas

'''

import time

from queue import Queue

class PoolException(Exception):

pass

class Pool(object):

'''一个数据库连接池'''

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):

'''释放资源,关闭池中的所有连接'''

print("release Pool..")

while self.__freeConns and not self.__freeConns.empty():

con = self.get()

con.release()

self.__freeConns = None

def _create_conn(self):

'''创建连接 '''

if self.db_type in dbcs:

return dbcs[self.db_type](**self.config);

def get(self, timeout=None):

'''获取一个连接

@param timeout:超时时间

'''

if timeout is None:

timeout = self.maxWait

conn = None

if self.__freeConns.empty():#如果容器是空的,直接创建一个连接

conn = self._create_conn()

else:

conn = self.__freeConns.get(timeout=timeout)

conn.pool = self

return conn

def free(self, conn):

'''将一个连接放回池中

@param conn: 连接对象

'''

conn.pool = None

if(self.__freeConns.full()):#如果当前连接池已满,直接关闭连接

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("连接已关闭")

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("无法创建数据库连接 或连接已关闭")

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中测试通过……

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值