Python 保证数据库连接在类中使用后关闭?

Python 保证数据库连接在类中使用后关闭?,python,python-3.x,Python,Python 3.x,我有一个包装器类,它是我们使用的许多数据库连接的子类。我希望它的行为类似于try/finally功能,但仍能给我类的灵活性和子类化潜力。这是我的基类,我想替换\uu del\uu方法,因为我在某个地方读到,无法保证它何时运行 class DatabaseConnBase: def __init__(self, conn_func, conn_info: MutableMapping): self._conn = None self.conn_func =

我有一个包装器类,它是我们使用的许多数据库连接的子类。我希望它的行为类似于
try/finally
功能,但仍能给我类的灵活性和子类化潜力。这是我的基类,我想替换
\uu del\uu
方法,因为我在某个地方读到,无法保证它何时运行

class DatabaseConnBase:
    def __init__(self, conn_func, conn_info: MutableMapping):
        self._conn = None
        self.conn_func = conn_func
        self.conn_info = conn_info

    def _initialize_connection(self):
        self._conn = self.conn_func(**self.conn_info)

    @property
    def conn(self):
        if not self._conn:
            self._initialize_connection()
        return self._conn

    @property
    def cursor(self):
        if not self._conn:
            self._initialize_connection()
        return self._conn.cursor()

    def __del__(self):
        if self._conn:
            self._conn.close()

    def commit(self):
        if not self._conn:
            raise AttributeError(
                'The connection has not been initialized, unable to commit '
                'transaction.'
            )
        self._conn.commit()

    def execute(
            self,
            query_or_stmt: str,
            verbose: bool = True,
            has_res: bool = False,
            auto_commit: bool = False
    ) -> Optional[Tuple[Any]]:
        """
        Creates a new cursor object, and executes the query/statement.  If
        `has_res` is `True`, then it returns the list of tuple results.

        :param query_or_stmt: The query or statement to run.
        :param verbose: If `True`, prints out the statement or query to STDOUT.
        :param has_res: Whether or not results should be returned.
        :param auto_commit: Immediately commits the changes to the database
         after the execute is performed.

        :return: If `has_res` is `True`, then a list of tuples.
        """
        cur = self.cursor
        if verbose:
            logger.info(f'Using {cur}')
            logger.info(f'Executing:\n{query_or_stmt}')

        cur.execute(query_or_stmt)

        if auto_commit:
            logger.info('Committing transaction...')
            self.commit()

        if has_res:
            logger.info('Returning results...')
            return cur.fetchall()

根据这一相关问题的首要答案:

垃圾收集对象时,将调用
\uuu del\uu
方法,但正如您所指出的,无法保证销毁对对象的引用后多久会发生这种情况


在您的情况下,由于您在尝试关闭连接之前检查连接是否存在,因此可以安全地多次调用
\uu del\uu
方法,因此您可以在销毁对对象的引用之前显式调用它。

使用上下文管理器显式执行此操作。您的类将需要
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu。