我可以将我的sqlite连接和光标放在一个函数中吗?

时间:2011-01-06 00:47:57

标签: python oop sqlite

我在想我会尝试使我的sqlite数据库连接成为一个函数而不是复制/粘贴连接和执行查询所需的~6行。 我想把它变得多才多艺,所以我可以使用相同的功能来创建/选择/插入/等...

以下是我的尝试。 “INSERT”和“CREATE TABLE”查询正在运行,但如果我执行“SELECT”查询,如何处理它在函数外部获取的值?
通常我想打印它所取的值,也可以用它们做其他事情。

当我这样做时,我得到一个错误

Traceback (most recent call last):
File "C:\Users\steini\Desktop\py\database\test3.py", line 15, in <module>
for row in connection('testdb45.db', "select * from users"):
ProgrammingError: Cannot operate on a closed database.

所以我猜连接需要打开,所以我可以从光标中获取值,但是我需要关闭它,这样文件就不会总是被锁定。

这是我的测试代码:

import sqlite3

def connection (db, arg, cubby):
    conn = sqlite3.connect(db)
    conn.execute('pragma foreign_keys = on')
    cur = conn.cursor()
    cur.execute(arg)
    for row in cur:
        cubby.append(row)
    conn.commit()
    conn.close()

cubby=[]
connection('testdb.db', "create table users ('user', 'email')", cubby)
connection('testdb.db', "insert into users ('user', 'email') values ('joey', 'foo@bar')", cubby)
for row in connection('testdb45.db', "select * from users", cubby):
    print row

我该如何做到这一点?

编辑:稍微修改了代码以使cur值附加到外部列表中,但仍然非常糟糕

2 个答案:

答案 0 :(得分:16)

我认为这个问题比起初看起来要困难得多。

您看到了错误,因为您已在“连接”功能中关闭了与数据库的连接。

您最好创建一个DatabaseManagement类,以管理单个连接。

类似的东西:

import sqlite3

class DatabaseManager(object):
    def __init__(self, db):
        self.conn = sqlite3.connect(db)
        self.conn.execute('pragma foreign_keys = on')
        self.conn.commit()
        self.cur = self.conn.cursor()

    def query(self, arg):
        self.cur.execute(arg)
        self.conn.commit()
        return self.cur

    def __del__(self):
        self.conn.close()

然后你应该可以做类似的事情:

dbmgr = DatabaseManager("testdb.db")
for row in dbmgr.query("select * from users"):
    print row

这将使对象在对象存在期间保持打开状态。

您仍然可能会发现这是一个更深层次的问题,但请四处游戏,看看哪些对您有用。

答案 1 :(得分:0)

它失败了,因为你的函数在返回之前关闭了连接。解决这个问题的方法是将函数转换为传递结果的生成器。像以下未经测试的代码应该可以工作:

def connection (db, arg):
    conn = sqlite3.connect(db)
    conn.execute('pragma foreign_keys = on')
    cur = conn.cursor()
    cur.execute(arg)
    for row in cur:
        yield row
    conn.commit()
    conn.close()

在调用此函数时,您必须格外小心消耗所有行,因为如果不这样做,则不会关闭连接。您可以通过查看实现with语法所需的函数来避免此问题。