я могу поместить свое соединение sqlite и курсор в функцию? - PullRequest
7 голосов
/ 06 января 2011

Я думал, что я попытаюсь сделать свое соединение базы данных 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 ]

16 голосов
/ 06 января 2011

Я думаю, что проблема немного сложнее, чем кажется на первый взгляд.

Вы видите ошибку, потому что вы закрыли соединение с базой данных в своей функции "connection".

Возможно, вам лучше создать класс 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

Это будет держать соединение открытым в течение всего времени существования объекта.

Вы все еще можете обнаружить, что это более серьезная проблема, но поиграйте и посмотрите, что работает для вас.

0 голосов
/ 06 января 2011

Сбой, потому что ваша функция закрывает соединение перед возвратом.Способ исправить это - превратить функцию в генератор, который передает результаты.Должно работать что-то вроде следующего непроверенного кода:

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.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...