使用sqlite3Python 中的模块,当收到SIGINT(例如Control-C)时,长时间运行的查询不会很快被中断/取消。sqlite3提供了一个interrupt()方法,但是没有如何使用的例子。
有没有一种简单的方法可以中断/取消通过 Python/sqlite3 运行的长时间运行的查询?
为了说明这一点,首先生成一个测试数据库和表:
import sqlite3
from random import randint
conn = sqlite3.connect("randtable.db", 10.0)
cursor = conn.cursor()
cursor.execute("CREATE TABLE randint (id integer, rand integer)")
for i in range(1000000):
if i % 1000 == 0:
print ("{0}...".format(i))
rand = randint(0,1000000)
cursor.execute("INSERT INTO randint VALUES ({0},{1})".format(i,rand))
conn.commit()
conn.close()
Run Code Online (Sandbox Code Playgroud)
然后在终端中执行长时间运行的 Python/sqlite3 脚本,并尝试使用 Control-C 中断它:
from __future__ import print_function
import sqlite3
def main():
# Long running query (pathological by design)
statement ='''
SELECT DISTINCT a.id,a.rand
FROM randint a
JOIN randint b ON a.id=b.rand
JOIN randint c ON a.id=c.rand
JOIN randint d ON a.id=d.rand
JOIN randint e ON a.id=e.rand
JOIN randint f ON a.id=f.rand
JOIN randint g ON a.id=g.rand
JOIN randint h ON a.id=h.rand
ORDER BY a.id limit 10'''
conn = sqlite3.connect('randtable.sqlite', 10.0)
cursor = conn.cursor()
print ("Executing query")
cursor.execute(statement)
rows = cursor.fetchall()
print ("ROWS:")
for row in rows:
print (" ", row)
conn.close()
return
if __name__ == "__main__":
main()
Run Code Online (Sandbox Code Playgroud)
在终端中运行上述脚本,然后按 Control-C(或以其他方式发送 SIGINT)最终将取消查询和脚本,但这可能需要相当长的时间,很多分钟。当按下 Control-C 时,在sqlite3命令行工具中运行的完全相同的查询几乎立即被取消。
提前致谢!
你的答案涵盖了它,但是(昨天让我忘记了 - 抱歉!)我记得我答应写一个答案,所以这里有另一个版本,演示你可以在没有全局变量的情况下做到这一点。我还使用了threading.Event此处而不是信号来演示有几种不同的方式向线程发出信号,表明是时候做某事了(但出于您的目的,请坚持使用信号,因为这非常适合对 Ctrl+C 做出反应):
import sqlite3
import time
import threading
# Background thread that'll kill our long running query after 1 second
def kill_it(connection, event):
event.wait()
time.sleep(1)
connection.interrupt()
# Make some tables with lots of data so we can make a long running query
def big_query(conn, kill_event):
print('Making big tables')
conn.execute(
"CREATE TABLE foo (i integer primary key, s text);")
conn.execute(
"CREATE TABLE bar (j integer primary key, s text);")
conn.execute(
"INSERT INTO foo VALUES %s" % ", ".join("(%d, 'foo')" % i for i in range(10000)))
conn.execute(
"INSERT INTO bar VALUES %s" % ", ".join("(%d, 'bar')" % i for i in range(10000)))
kill_event.set()
print('Running query')
cur = conn.cursor()
cur.execute(
"SELECT * FROM foo, bar")
print(len(cur.fetchall()))
def main():
conn = sqlite3.connect('foo.db')
kill_event = threading.Event()
kill_thread = threading.Thread(target=kill_it, args=(conn, kill_event))
kill_thread.start()
big_query(conn, kill_event)
kill_thread.join()
if __name__ == '__main__':
main()
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2642 次 |
| 最近记录: |