You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将Python类实例持久化存储到SQLite3数据库?

两种将Python类实例持久化到SQLite3的方案

方案一:结构化存储(推荐)

这种方式把类的属性映射到数据库表的字段,存储和读取时手动处理属性与数据库记录的转换,优点是数据透明、安全,便于直接操作数据库中的数据。

实现代码

import sqlite3

class Foo:
    def __init__(self, foo1=0, instance_id=None):
        self.foo1 = foo1
        # 用instance_id绑定数据库中的记录ID,方便后续更新
        self.instance_id = instance_id

    def increment(self):
        self.foo1 += 1

# 初始化数据库连接
def init_db():
    conn = sqlite3.connect('foo_instances.db')
    cursor = conn.cursor()
    # 创建存储Foo实例的表,instance_id为主键自增
    cursor.execute('''
        CREATE TABLE IF NOT EXISTS foos (
            instance_id INTEGER PRIMARY KEY AUTOINCREMENT,
            foo1 INTEGER NOT NULL
        )
    ''')
    conn.commit()
    conn.close()

# 保存Foo实例到数据库
def save_foo(foo):
    conn = sqlite3.connect('foo_instances.db')
    cursor = conn.cursor()
    if foo.instance_id is None:
        # 新实例,插入记录
        cursor.execute('INSERT INTO foos (foo1) VALUES (?)', (foo.foo1,))
        foo.instance_id = cursor.lastrowid
    else:
        # 已有实例,更新记录
        cursor.execute('UPDATE foos SET foo1 = ? WHERE instance_id = ?', (foo.foo1, foo.instance_id))
    conn.commit()
    conn.close()

# 从数据库加载所有Foo实例
def load_all_foos():
    conn = sqlite3.connect('foo_instances.db')
    cursor = conn.cursor()
    cursor.execute('SELECT instance_id, foo1 FROM foos')
    rows = cursor.fetchall()
    conn.close()
    # 把数据库记录转换为Foo实例
    foos = []
    for row in rows:
        instance_id, foo1 = row
        foo = Foo(foo1, instance_id)
        foos.append(foo)
    return foos

# 示例用法
if __name__ == '__main__':
    init_db()

    # 创建实例并保存
    foo = Foo()
    foo.increment()
    save_foo(foo)

    foo2 = Foo(5)
    save_foo(foo2)

    # 重启程序后加载实例
    loaded_foos = load_all_foos()
    print(loaded_foos)  # 输出类似 [<__main__.Foo object at 0x...>, <__main__.Foo object at 0x...>]

    # 修改加载后的实例并保存
    for f in loaded_foos:
        f.increment()
        save_foo(f)

    # 再次验证
    reloaded_foos = load_all_foos()
    for f in reloaded_foos:
        print(f.foo1)  # 输出2和6

方案二:Pickle序列化存储

利用Python的pickle模块把整个实例序列化为二进制数据,存储到SQLite的BLOB字段中。这种方式无需手动映射属性,但数据不可读,且加载不可信数据存在安全风险,仅适合内部使用。

实现代码

import sqlite3
import pickle

class Foo:
    def __init__(self):
        self.foo1 = 0

    def increment(self):
        self.foo1 += 1

# 初始化数据库
def init_db():
    conn = sqlite3.connect('foo_pickle.db')
    cursor = conn.cursor()
    cursor.execute('''
        CREATE TABLE IF NOT EXISTS foos (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            instance_blob BLOB NOT NULL
        )
    ''')
    conn.commit()
    conn.close()

# 保存实例到数据库
def save_foo(foo):
    conn = sqlite3.connect('foo_pickle.db')
    cursor = conn.cursor()
    # 序列化实例为二进制
    serialized = pickle.dumps(foo)
    cursor.execute('INSERT INTO foos (instance_blob) VALUES (?)', (serialized,))
    conn.commit()
    conn.close()

# 加载所有实例
def load_all_foos():
    conn = sqlite3.connect('foo_pickle.db')
    cursor = conn.cursor()
    cursor.execute('SELECT instance_blob FROM foos')
    rows = cursor.fetchall()
    conn.close()
    # 反序列化二进制为实例
    foos = []
    for row in rows:
        blob = row[0]
        foo = pickle.loads(blob)
        foos.append(foo)
    return foos

# 示例用法
if __name__ == '__main__':
    init_db()

    # 创建并保存实例
    foo = Foo()
    foo.increment()
    save_foo(foo)

    foo2 = Foo()
    save_foo(foo2)

    # 加载实例
    loaded_foos = load_all_foos()
    print(loaded_foos)  # 输出类似 [<__main__.Foo object at 0x...>, <__main__.Foo object at 0x...>]

    # 修改并重新保存(注意:若要更新原实例,需记录id并执行UPDATE操作,示例为演示重新插入新记录)
    for f in loaded_foos:
        f.increment()
        save_foo(f)

    reloaded = load_all_foos()
    for f in reloaded:
        print(f.foo1)  # 输出2,1,2,1

注意事项

  • 方案二中如果需要更新原实例,需在表中记录id,保存时根据id更新对应的blob字段,避免重复插入。
  • Pickle序列化存在版本兼容性问题,如果后续修改了Foo类的结构,旧的序列化数据可能无法正常加载。

内容的提问来源于stack exchange,提问作者Angel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 20:33:21