数据库是锁定的,但所有语句后面都是提交?

时间:2015-10-22 05:35:51

标签: python sqlite

我正在研究一种名为Skybot的模块化机器人的IRC机器人。

默认情况下,还有另外两个模块使用sqlite3数据库;他们都被删除了,他们的桌子掉了下来,所以我知道问题出在我正在做的事情上。

我只在整个事情中调用3 db.execute()个语句,并且它们都立即被提交。这个问题也没有受到查询的影响,但锁仍然存在。

相关代码:

def db_init(db):
    db.execute("create table if not exists searches"
               "(search_string UNIQUE PRIMARY KEY,link)")
    db.commit()

    return db


def get_link(db, inp):
        row = db.execute("select link from searches where"
                         " search_string=lower(?) limit 1",
                         (inp.lower(),)).fetchone()
    db.commit()
    return row


def store_link(db, stub, search):
    db.execute("insert into searches (search_string, link) VALUES (?, ?)", (search.lower(), stub))
    db.commit()
    return stub

如果脚本只需要触摸db_init()get_link()就可以轻松通过,但如果需要在数据库解锁时调用store_link(),则会执行插入,但不会似乎是以未来调用get_link()可以读取它直到机器人重新启动的方式提交它。

机器人的db.py:

import os
import sqlite3


def get_db_connection(conn, name=''):
"returns an sqlite3 connection to a persistent database"

if not name:
    name = '%s.%s.db' % (conn.nick, conn.server)

filename = os.path.join(bot.persist_dir, name)
return sqlite3.connect(filename, isolation_level=None)

bot.get_db_connection = get_db_connection

我自己调整了isolation_level,原来是timeout=10。我很难过。

编辑:get_db_connection()

的用法

main.py(主循环):

def run(func, input):
args = func._args

if 'inp' not in input:
    input.inp = input.paraml

if args:
    if 'db' in args and 'db' not in input:
        input.db = get_db_connection(input.conn)
    if 'input' in args:
        input.input = input
    if 0 in args:
        out = func(input.inp, **input)
    else:
        kw = dict((key, input[key]) for key in args if key in input)
        out = func(input.inp, **kw)
else:
    out = func(input.inp)
if out is not None:
    input.reply(unicode(out))

...

def start(self):
    uses_db = 'db' in self.func._args
    db_conns = {}
    while True:
        input = self.input_queue.get()

        if input == StopIteration:
            break

        if uses_db:
            db = db_conns.get(input.conn)
            if db is None:
                db = bot.get_db_connection(input.conn)
                db_conns[input.conn] = db
            input.db = db

        try:
            run(self.func, input)
        except:
            traceback.print_exc()

2 个答案:

答案 0 :(得分:0)

如上所述,在您的函数中发送conn以及db。如果您自己编写代码,那么您将知道数据库的实际位置。通常你会做类似的事情:

db      = sqlite3.connect('database.db')
conn    = db.cursor()

然后用于一般用法:

    db.execute("...")
    conn.commit()

因此,在您的情况下:

def db_init(conn,db):
    db.execute("create table if not exists searches"
               "(search_string UNIQUE PRIMARY KEY,link)")
    conn.commit()

    return db 


def get_link(conn,db, inp):
        row = db.execute("select link from searches where"
                         " search_string=lower(?) limit 1",
                         (inp.lower(),)).fetchone()
    conn.commit()
    return row


def store_link(conn,db, stub, search):
    db.execute("insert into searches (search_string, link) VALUES (?, ?)", (search.lower(), stub))
    conn.commit()
    return stub

答案 1 :(得分:0)

基于您已将isolation_level设置为自动更新:

sqlite3.connect(filename, isolation_level=None)

您的代码中的commit语句不需要任何内容​​

编辑:
execute语句中包含您的try语句,以便您至少有机会了解正在发生的事情,例如

import sqlite3
def get_db(name=""):
    if not name:
        name = "db1.db"
    return sqlite3.connect(name, isolation_level=None)
connection = get_db()
cur = connection.cursor()
try:
    cur.execute("create table if not exists searches"
               "(search_string UNIQUE PRIMARY KEY,link)")
except sqlite3.Error as e:
    print 'Searches create Error '+str(e)
try:
    cur.execute("insert into searches (search_string, link) VALUES (?, ?)", ("my search", "other"))
except sqlite3.Error as e:
    print 'Searches insert Error '+str(e)
cur.execute("select link from searches where search_string=? limit 1", ["my search"])
s_data = cur.fetchone()
print 'Result:', s_data