浏览 5972 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2009-04-17
最后修改:2009-04-17
在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中测试通过…… 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2009-08-06
请问class PoolingConnection(object, metaclass=ABCMeta): 的意思是什么?
为何我的提示错误,execpt:) 改为class PoolingConnection(object): 或class PoolingConnection(ABCMeta): 都正常,第二句和你写的那个等价吗 初学django,多谢指导~ |
|
返回顶楼 | |
发表时间:2009-08-06
iamsk 写道 请问class PoolingConnection(object, metaclass=ABCMeta): 的意思是什么? 为何我的提示错误,execpt:) 改为class PoolingConnection(object): 或class PoolingConnection(ABCMeta): 都正常,第二句和你写的那个等价吗 初学django,多谢指导~ 查了下,在python 2.x里 元类是在类里加 __metaclass__ = type |
|
返回顶楼 | |
发表时间:2009-08-07
呵呵,我主要看的是python3k的文档,python2.x的没怎么看
|
|
返回顶楼 | |
发表时间:2009-10-08
弱引用可以解决这个问题。请搜索关键字"weakref".
例如: import weakref class A: def __init__(self): print 'A.__init__' self.b = None def __del__(self): print 'A.__del__' class B: def __init__(self): print 'B.__init__' self.a = None def __del__(self): print 'B.__del__' if __name__ == '__main__': a = A() b = B() a.b = weakref.proxy(b) b.a = a |
|
返回顶楼 | |
发表时间:2009-10-08
谢谢LS提醒
|
|
返回顶楼 | |