- r - 以节省内存的方式增长 data.frame
- ruby-on-rails - ruby/ruby on rails 内存泄漏检测
- android - 无法解析导入android.support.v7.app
- UNIX 域套接字与共享内存(映射文件)
使用 Python 的 sqlite3 module 时关闭游标有什么好处吗? ?或者它只是 DB API v2.0 的产物那可能只对其他数据库有用?
connection.close() 是有道理的释放资源;然而,尚不清楚 cursor.close() 究竟做了什么,它是释放了一些资源还是什么都不做。它的文档没有启发性:
>>> import sqlite3
>>> conn = sqlite3.connect(':memory:')
>>> c = conn.cursor()
>>> help(c.close)
Help on built-in function close:
close(...)
Closes the cursor.
请注意,这是一个与 Why do you need to create a cursor when querying a sqlite database? 完全不同的问题.我知道游标是做什么用的。问题是关于 cursor.close()
方法实际做什么以及调用它是否有任何好处。
最佳答案
CPython _sqlite3.Cursor.close
对应于 pysqlite_cursor_close
除了一些完整性检查并将其标记为已关闭外,does this :
if (self->statement) {
(void)pysqlite_statement_reset(self->statement);
Py_CLEAR(self->statement);
}
pysqlite_statement_reset
依次调用sqlite3_reset
来自 SQLite 的 C API:
The sqlite3_reset() function is called to reset a prepared statement object back to its initial state, ready to be re-executed. Any SQL statement variables that had values bound to them using the sqlite3_bind_*() API retain their values. Use sqlite3_clear_bindings() to reset the bindings.
[...]
The sqlite3_reset(S) interface does not change the values of any bindings on the prepared statement S.
Prepared Statement Object API用于绑定(bind)参数,例如在 _sqlite3.Cursor.execute
中。因此,如果使用 sqlite3_clear_bindings
,它可能已经能够释放一些用于存储参数的内存,但我没有看到它在 CPython/pysqlite 的任何地方被调用。
我使用 memory-profiler绘制内存使用情况图表并生成逐行报告。
import logging
import sqlite3
import time
# For the function brackets to appear on the chart leave this out:
#
# If your Python file imports the memory profiler
# "from memory_profiler import profile" these timestamps will not be
# recorded. Comment out the import, leave your functions decorated,
# and re-run.
#
# from memory_profiler import profile
class CursorCuriosity:
cursor_num = 20_000
param_num = 200
def __init__(self):
self.conn = sqlite3.connect(':memory:')
self.cursors = []
@profile
def create(self):
logging.info('Creating cursors')
sql = 'SELECT {}'.format(','.join(['?'] * self.param_num))
for i in range(self.cursor_num):
params = [i] * self.param_num
cur = self.conn.execute(sql, params)
self.cursors.append(cur)
@profile
def close(self):
logging.info('Closing cursors')
for cur in self.cursors:
cur.close()
@profile
def delete(self):
logging.info('Destructing cursors')
self.cursors.clear()
@profile
def disconnect(self):
logging.info('Disconnecting')
self.conn.close()
del self.conn
@profile
def main():
curcur = CursorCuriosity()
logging.info('Sleeping before calling create()')
time.sleep(2)
curcur.create()
logging.info('Sleeping before calling close()')
time.sleep(2)
curcur.close()
logging.info('Sleeping before calling delete()')
time.sleep(2)
curcur.delete()
logging.info('Sleeping before calling disconnect()')
time.sleep(2)
curcur.disconnect()
logging.info('Sleeping before exit')
time.sleep(2)
if __name__ == '__main__':
logging.basicConfig(level='INFO', format='%(asctime)s %(message)s')
main()
我首先运行它并注释掉 profile
导入以获得绘图。
mprof run -T 0.05 cursor_overhead.py
mprof plot
然后通过导入在终端中获取输出。
mprof run -T 0.05 cursor_overhead.py
Line # Mem usage Increment Occurences Line Contents
============================================================
51 19.1 MiB 19.1 MiB 1 @profile
52 def main():
53 19.1 MiB 0.0 MiB 1 curcur = CursorCuriosity()
54
55 19.1 MiB 0.0 MiB 1 logging.info('Sleeping before calling create()')
56 19.1 MiB 0.0 MiB 1 time.sleep(2)
57 2410.3 MiB 2391.2 MiB 1 curcur.create()
58
59 2410.3 MiB 0.0 MiB 1 logging.info('Sleeping before calling close()')
60 2410.3 MiB 0.0 MiB 1 time.sleep(2)
61 2410.3 MiB 0.0 MiB 1 curcur.close()
62
63 2410.3 MiB 0.0 MiB 1 logging.info('Sleeping before calling delete()')
64 2410.3 MiB 0.0 MiB 1 time.sleep(2)
65 1972.2 MiB -438.1 MiB 1 curcur.delete()
66
67 1972.2 MiB 0.0 MiB 1 logging.info('Sleeping before calling disconnect()')
68 1972.2 MiB 0.0 MiB 1 time.sleep(2)
69 1872.7 MiB -99.5 MiB 1 curcur.disconnect()
70
71 1872.7 MiB 0.0 MiB 1 logging.info('Sleeping before exit')
72 1872.7 MiB 0.0 MiB 1 time.sleep(2)
以及完整性的个别方法。
Line # Mem usage Increment Occurences Line Contents
============================================================
24 19.1 MiB 19.1 MiB 1 @profile
25 def create(self):
26 19.1 MiB 0.0 MiB 1 logging.info('Creating cursors')
27 19.1 MiB 0.0 MiB 1 sql = 'SELECT {}'.format(','.join(['?'] * self.param_num))
28 2410.3 MiB 0.0 MiB 20001 for i in range(self.cursor_num):
29 2410.1 MiB 0.0 MiB 20000 params = [i] * self.param_num
30 2410.3 MiB 2374.3 MiB 20000 cur = self.conn.execute(sql, params)
31 2410.3 MiB 16.9 MiB 20000 self.cursors.append(cur)
Line # Mem usage Increment Occurences Line Contents
============================================================
33 2410.3 MiB 2410.3 MiB 1 @profile
34 def close(self):
35 2410.3 MiB 0.0 MiB 1 logging.info('Closing cursors')
36 2410.3 MiB 0.0 MiB 20001 for cur in self.cursors:
37 2410.3 MiB 0.0 MiB 20000 cur.close()
Line # Mem usage Increment Occurences Line Contents
============================================================
39 2410.3 MiB 2410.3 MiB 1 @profile
40 def delete(self):
41 2410.3 MiB 0.0 MiB 1 logging.info('Destructing cursors')
42 1972.2 MiB -438.1 MiB 1 self.cursors.clear()
Line # Mem usage Increment Occurences Line Contents
============================================================
44 1972.2 MiB 1972.2 MiB 1 @profile
45 def disconnect(self):
46 1972.2 MiB 0.0 MiB 1 logging.info('Disconnecting')
47 1972.2 MiB 0.0 MiB 1 self.conn.close()
48 1872.7 MiB -99.5 MiB 1 del self.conn
sqlite3.Cursor
不会释放内存(但会做一些工作,操纵 SQLite 准备语句的状态)sqlite3.Connection
释放内存(关闭不会)关于python - 为什么在 Python 中关闭 Sqlite3 的游标,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43927799/
我正在处理一组标记为 160 个组的 173k 点。我想通过合并最接近的(到 9 或 10 个组)来减少组/集群的数量。我搜索过 sklearn 或类似的库,但没有成功。 我猜它只是通过 knn 聚类
我有一个扁平数字列表,这些数字逻辑上以 3 为一组,其中每个三元组是 (number, __ignored, flag[0 or 1]),例如: [7,56,1, 8,0,0, 2,0,0, 6,1,
我正在使用 pipenv 来管理我的包。我想编写一个 python 脚本来调用另一个使用不同虚拟环境(VE)的 python 脚本。 如何运行使用 VE1 的 python 脚本 1 并调用另一个 p
假设我有一个文件 script.py 位于 path = "foo/bar/script.py"。我正在寻找一种在 Python 中通过函数 execute_script() 从我的主要 Python
这听起来像是谜语或笑话,但实际上我还没有找到这个问题的答案。 问题到底是什么? 我想运行 2 个脚本。在第一个脚本中,我调用另一个脚本,但我希望它们继续并行,而不是在两个单独的线程中。主要是我不希望第
我有一个带有 python 2.5.5 的软件。我想发送一个命令,该命令将在 python 2.7.5 中启动一个脚本,然后继续执行该脚本。 我试过用 #!python2.7.5 和http://re
我在 python 命令行(使用 python 2.7)中,并尝试运行 Python 脚本。我的操作系统是 Windows 7。我已将我的目录设置为包含我所有脚本的文件夹,使用: os.chdir("
剧透:部分解决(见最后)。 以下是使用 Python 嵌入的代码示例: #include int main(int argc, char** argv) { Py_SetPythonHome
假设我有以下列表,对应于及时的股票价格: prices = [1, 3, 7, 10, 9, 8, 5, 3, 6, 8, 12, 9, 6, 10, 13, 8, 4, 11] 我想确定以下总体上最
所以我试图在选择某个单选按钮时更改此框架的背景。 我的框架位于一个类中,并且单选按钮的功能位于该类之外。 (这样我就可以在所有其他框架上调用它们。) 问题是每当我选择单选按钮时都会出现以下错误: co
我正在尝试将字符串与 python 中的正则表达式进行比较,如下所示, #!/usr/bin/env python3 import re str1 = "Expecting property name
考虑以下原型(prototype) Boost.Python 模块,该模块从单独的 C++ 头文件中引入类“D”。 /* file: a/b.cpp */ BOOST_PYTHON_MODULE(c)
如何编写一个程序来“识别函数调用的行号?” python 检查模块提供了定位行号的选项,但是, def di(): return inspect.currentframe().f_back.f_l
我已经使用 macports 安装了 Python 2.7,并且由于我的 $PATH 变量,这就是我输入 $ python 时得到的变量。然而,virtualenv 默认使用 Python 2.6,除
我只想问如何加快 python 上的 re.search 速度。 我有一个很长的字符串行,长度为 176861(即带有一些符号的字母数字字符),我使用此函数测试了该行以进行研究: def getExe
list1= [u'%app%%General%%Council%', u'%people%', u'%people%%Regional%%Council%%Mandate%', u'%ppp%%Ge
这个问题在这里已经有了答案: Is it Pythonic to use list comprehensions for just side effects? (7 个答案) 关闭 4 个月前。 告
我想用 Python 将两个列表组合成一个列表,方法如下: a = [1,1,1,2,2,2,3,3,3,3] b= ["Sun", "is", "bright", "June","and" ,"Ju
我正在运行带有最新 Boost 发行版 (1.55.0) 的 Mac OS X 10.8.4 (Darwin 12.4.0)。我正在按照说明 here构建包含在我的发行版中的教程 Boost-Pyth
学习 Python,我正在尝试制作一个没有任何第 3 方库的网络抓取工具,这样过程对我来说并没有简化,而且我知道我在做什么。我浏览了一些在线资源,但所有这些都让我对某些事情感到困惑。 html 看起来
我是一名优秀的程序员,十分优秀!