Skip to content

Instantly share code, notes, and snippets.

@fbigun
Last active August 29, 2015 14:08
Show Gist options
  • Select an option

  • Save fbigun/595f022ab6736dfeedb5 to your computer and use it in GitHub Desktop.

Select an option

Save fbigun/595f022ab6736dfeedb5 to your computer and use it in GitHub Desktop.

Revisions

  1. fbigun revised this gist Oct 27, 2014. 2 changed files with 0 additions and 1 deletion.
    1 change: 0 additions & 1 deletion README.md
    Original file line number Diff line number Diff line change
    @@ -1,4 +1,3 @@

    ***Python***中如果对象定义了`__del__`方法的话,在对象的引用记数为0时会自动调用`__del__`方法
    (很象c++中的析构函数),但如果A对象引用B对象,B对象又引用A对象,就形成循环引用,此时A,B对象
    引用次数都为1。python就无法正常调用`__del__`方法,原计划在`__del__`方法里释放的资源自然也就无
    File renamed without changes.
  2. fbigun revised this gist Oct 27, 2014. 2 changed files with 11 additions and 2 deletions.
    2 changes: 0 additions & 2 deletions README
    Original file line number Diff line number Diff line change
    @@ -1,2 +0,0 @@
    在***Python***中如果对象定义了`__del__`方法的话,在对象的引用记数为0时会自动调用`__del__`方法(很象c++中的析构函数),但如果A对象引用B对象,B对象又引用A对象,就形成循环引用,此时A,B对象引用次数都为1。python就无法正常调用`__del__`方法,原计划在`__del__`方法里释放的资源自然也就无法释放。
    一个连接池拥有多个连接,而每个连接又拥有这个连接池的实例(一个叫pool的属性)。这样就产生了刚刚说的哪个问题。我想到的办法就是在每次从池中获取连接的时候将连接的pool设置为当前实例,然后在归还这个连接的时候再将其设置为***None***,并且要在这个连接对象的`__del__`方法中将pool属性设置为***None***。具体看代码吧。(目前只实现了SQLite3的)
    11 changes: 11 additions & 0 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,11 @@

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


    一个连接池拥有多个连接,而每个连接又拥有这个连接池的实例(一个叫pool的属性)。这样就产生了刚刚
    说的哪个问题。我想到的办法就是在每次从池中获取连接的时候将连接的pool设置为当前实例,然后在归
    还这个连接的时候再将其设置为***None***,并且要在这个连接对象的`__del__`方法中将pool属性设置为
    ***None***。具体看代码吧。(目前只实现了SQLite3的)
  3. fbigun created this gist Oct 27, 2014.
    121 changes: 121 additions & 0 deletions Python代码
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,121 @@
    '''
    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()
    2 changes: 2 additions & 0 deletions README
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,2 @@
    在***Python***中如果对象定义了`__del__`方法的话,在对象的引用记数为0时会自动调用`__del__`方法(很象c++中的析构函数),但如果A对象引用B对象,B对象又引用A对象,就形成循环引用,此时A,B对象引用次数都为1。python就无法正常调用`__del__`方法,原计划在`__del__`方法里释放的资源自然也就无法释放。
    一个连接池拥有多个连接,而每个连接又拥有这个连接池的实例(一个叫pool的属性)。这样就产生了刚刚说的哪个问题。我想到的办法就是在每次从池中获取连接的时候将连接的pool设置为当前实例,然后在归还这个连接的时候再将其设置为***None***,并且要在这个连接对象的`__del__`方法中将pool属性设置为***None***。具体看代码吧。(目前只实现了SQLite3的)