在Python中使用sqlite,是否必须关闭游标?

56 投票
9 回答
36470 浏览
提问于 2025-04-15 19:42

这里有个场景。在你的函数里,你用一个游标执行一些操作,但其中一个操作失败了,抛出了一个异常。这样一来,你的程序就会在关闭游标之前退出这个函数。那么,这个游标会不会一直占用空间呢?我需要手动关闭这个游标吗?

另外,Python的文档里有一个关于游标使用的例子,提到:“如果我们用完了游标,也可以关闭它。”这里的关键词是“可以”,而不是“必须”。这到底是什么意思呢?

9 个回答

14

大家好,

我在用Python 3.8和sqlite3写代码的时候,发现我的程序内存使用量逐渐增加,像是有内存泄漏。我追踪了一下,发现问题可能出在我的数据库类上。原来,我在打开和使用数据库游标后,从来没有把它关闭。程序运行期间,数据库一直是打开的,只有在退出时才会关闭。

后来我开始在所有使用游标的数据库操作中关闭游标,结果内存泄漏的问题就解决了,内存使用量也变得稳定了。

所以我建议大家花点时间去关闭游标。这样做不仅让代码更规范,而且显然也有助于控制内存的使用。

下面是我关闭游标的一个例子:

def write_to_db(self, cache_item:CacheEntry):
        '''Write a single cache entry to the database'''
        crsr = self._db_con.cursor()

        # Load some data elements
        fax_line_path = cache_item._dir_part
        phone_line = cache_item._phone_line
        sub_folder = cache_item._subfolder
        fname = cache_item._fname
        work_done = cache_item.get_workdone()

        try:
            crsr.execute(FilenameCacheDB.INSERT_CACHE,
                             (fax_line_path, 
                              phone_line, 
                              sub_folder, 
                              fname, 
                              work_done))

        except Exception as e:
            LOG.warning(f"Could not write {cache_item} to db because {e}")
            raise e

        finally:
            #
            # I was *not* closing the cursor prior
            #
            crsr.close()
            self._db_con.commit()
15

你并不一定要在游标上调用 close() 方法;它可以像其他对象一样被垃圾回收。

不过,即使等垃圾回收听起来没问题,我觉得还是应该养成好习惯,确保像数据库游标这样的资源在出现异常时也能被关闭。

26

这可能是个好主意(虽然在sqlite中可能没什么大影响,我不太确定,但这样做会让你的代码更容易移植)。而且,使用最近的Python版本(2.5及以上)来实现这一点非常简单:

from __future__ import with_statement
from contextlib import closing

with closing(db.cursor()) as cursor:
    # do some stuff

撰写回答