在Python中使用sqlite,是否必须关闭游标?
这里有个场景。在你的函数里,你用一个游标执行一些操作,但其中一个操作失败了,抛出了一个异常。这样一来,你的程序就会在关闭游标之前退出这个函数。那么,这个游标会不会一直占用空间呢?我需要手动关闭这个游标吗?
另外,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