python sqlite3 每执行一个操作就需要打开关闭的疑惑?

本人第一次接触数据库, 许多操作还不熟练, 遇到一点疑惑如下:

使用的python版本为3.6

先上代码:

import sqlite3
from pathlib import Path

def open_db():
    root = Path(__file__).parent.parent
    db_path = str(root / 'db/data.sqlite')
    conn = sqlite3.connect(db_path)
    cursor = conn.cursor()
    return conn, cursor

def close_db(conn, cursor):
    conn.commit()
    cursor.close()
    conn.close()

class User:

    def __init__(self, form):
        self.username = form.get('username', '')
        self.password = form.get('password', '')
    
    @classmethod
    def add(cls, user):
        conn, cursor = open_db()
        sql_insert = """
        INSERT INTO
            User(xxx)
        VALUES
            (xxx);
        """
        conn.execute(sql_insert)
        close_db(conn, cursor)
        
    @classmethod
    def update(cls, id, password):
        conn, cursor = open_db()
        sql_update = """
        UPDATE
            `User`
        SET
            `email`=?
        WHERE
            `id`=?
        """
        conn.execute(sql_update, (id, password))
        close_db(conn, cursor)

有两个函数open_dbclose_db分别用来打开和关闭数据库, User类有两个类方法addupdate, 用来增加记录和更新记录. 现在的问题在于, 我每写一个有关数据库操作的方法就需要调用一次非常麻烦, 请问有没有更加简单的方法进行操作?

本人第一接触数据库方面知识, 若有不足, 还请见谅. 真诚希望各位前辈能解答, 不胜感激!

阅读 4.6k
1 个回答

这个问题放了几天了好像也没有前辈解答, 我就自己回答一下吧, 解答方案可能存在错误, 也请前辈及时指出

1, 用with

文档里面说:

Connection objects can be used as context managers that automatically commit or rollback transactions. In the event of an exception, the transaction is rolled back; otherwise, the transaction is committed:

大概就是说连接的数据库对象可以作为上下文管理器进行自动提交或者回滚, 所以代码大致如下:

conn = sqlite3.connect(data.sqlite)
sql = """xxxx"""
with conn:
    cursor = conn.cursor()
    cursor.execute(sql)
    result = cursor.fetchall()

当然也可以自己写一个上下文管理器, 如下:

class dbopen:
    def __init__(self, path):
        self.path = path
        self.conn = None
        self.cursor = None

    def __enter__(self):
        self.conn = sqlite3.connect(self.path)
        self.cursor = self.conn.cursor()
        return self.cursor

    def __exit__(self, exc_class, exc, traceback):
        self.conn.commit()
        self.conn.close()

with dbopen('data.sqlite') as cursor:
    sql = """xxx"""
    cursor.execute(sql)
    print(cursor.fetchall())

2, 用装饰器
其实我不知道这个是不是一个好办法, 也很少看到有人这么做, 不过好像也可以用, 代码如下:

def dbconn(query):
    def wrapper(cls, *args, **kwargs):
        conn = sqlite3.connect(db_path)
        result = query(cls, conn, *args, **kwargs)
        conn.commit()
        conn.close()
        return result
    return wrapper

class User:

    @classmethod
    @dbconn
    def select_all(cls, conn):
        cursor = conn.cursor()
        sql = """xxx"""
        cursor.execute(sql)
        return cursor.fetchall()

Reference:

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题