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

Python中SQLite/SQLAlchemy数值转换及人脸编码恢复咨询

解答你的两个技术问题

我来帮你一步步解决这两个问题:

一、在Python的SQLite或SQLAlchemy中进行数值转换

SQLite本身是弱类型数据库,但我们可以在Python层面或者通过SQLAlchemy的类型约束来处理数值转换,分两种场景来说:

1. 原生SQLite操作

直接用sqlite3库时,你可以在插入/查询时手动用Python的类型转换函数(比如int()、float())处理数据:

import sqlite3

# 连接数据库
conn = sqlite3.connect('test.db')
c = conn.cursor()

# 创建表
c.execute("CREATE TABLE IF NOT EXISTS numbers (id INTEGER PRIMARY KEY AUTOINCREMENT, value TEXT)")

# 插入时:把数值转成字符串存入
c.execute("INSERT INTO numbers (value) VALUES (?)", (str(12.34),))

# 查询时:把取出的字符串转成数值
c.execute("SELECT value FROM numbers WHERE id=1")
result = c.fetchone()
if result:
    num = float(result[0])
    print(type(num))  # <class 'float'>

conn.commit()
conn.close()

如果希望数据库字段更贴合数值类型,也可以直接存储数值,SQLite会自动适配,查询时直接得到对应类型:

# 插入时直接传数值
c.execute("INSERT INTO numbers (value) VALUES (?)", (12.34,))
# 查询时直接得到float类型
result = c.fetchone()
print(type(result[0]))  # <class 'float'>

2. SQLAlchemy操作

SQLAlchemy提供了强类型的列定义,会自动帮你处理Python和数据库之间的类型映射,常用的数值类型有Integer、Float、Numeric等:

from sqlalchemy import create_engine, MetaData, Table, Column, Integer, Float

engine = create_engine('sqlite:///test.db', echo=True)
meta = MetaData()

# 定义带数值类型的表
numbers = Table(
    'numbers', meta,
    Column('id', Integer, primary_key=True),
    Column('value', Float)  # 指定为Float类型
)
meta.create_all(engine)

# 插入时直接传Python数值,SQLAlchemy自动处理转换
with engine.connect() as conn:
    conn.execute(numbers.insert().values(value=12.34))

# 查询时直接得到float类型的结果
with engine.connect() as conn:
    result = conn.execute(numbers.select().where(numbers.c.id == 1)).fetchone()
    if result:
        print(type(result.value))  # <class 'float'>

如果需要自定义数值转换逻辑(比如处理特殊格式的数值),还可以用SQLAlchemy的TypeDecorator来实现自定义类型转换。

二、恢复存入SQLite的人脸编码数组

首先要说明:你遇到的二进制问题,是因为直接把numpy数组(face_recognition返回的编码是numpy数组)当成普通数据存入了数据库,SQLite自动把这个Python对象序列化成了二进制。正确的做法是先把numpy数组序列化成可存储的格式,再存入数据库,读取时反序列化即可。

正确的存储与恢复方案(推荐用numpy原生序列化)

face_recognition.face_encodings()返回的是一个包含numpy数组的列表,我们可以用numpy的tobytes()把数组转成字节流,存入SQLite的BLOB类型字段,读取时用numpy.frombuffer()恢复成原数组。

修正后的存储代码

import sqlite3
import numpy as np
import face_recognition

# 加载图片并获取人脸编码
new_picture = face_recognition.load_image_file("你的图片路径.jpg")
face_encodings = face_recognition.face_encodings(new_picture)

if face_encodings:  # 确保检测到人脸
    encoding = face_encodings[0]  # 取第一个人脸的编码
    conn = sqlite3.connect('image.db')
    c = conn.cursor()

    # 创建带BLOB字段的表(专门存字节流)
    c.execute("CREATE TABLE IF NOT EXISTS img(id INTEGER PRIMARY KEY AUTOINCREMENT, imagecode BLOB)")

    # 把numpy数组转成字节存入
    c.execute("INSERT INTO img(imagecode) VALUES (?)", (encoding.tobytes(),))

    conn.commit()
    c.close()
    conn.close()

恢复原始人脸编码的代码

import sqlite3
import numpy as np

conn = sqlite3.connect('image.db')
c = conn.cursor()

# 查询指定记录的人脸编码
c.execute("SELECT imagecode FROM img WHERE id=1")
result = c.fetchone()

if result:
    # 从二进制字节恢复成numpy数组,注意人脸编码是float64类型
    original_encoding = np.frombuffer(result[0], dtype=np.float64)
    print(original_encoding)  # 这就是你需要的原始人脸编码数组

c.close()
conn.close()

用SQLAlchemy实现的版本

如果你习惯用SQLAlchemy,可以用LargeBinary类型来存储字节流,逻辑和原生SQLite一致:

from sqlalchemy import create_engine, MetaData, Table, Column, Integer, LargeBinary
import numpy as np
import face_recognition

new_picture = face_recognition.load_image_file("你的图片路径.jpg")
face_encodings = face_recognition.face_encodings(new_picture)

if face_encodings:
    encoding = face_encodings[0]
    engine = create_engine('sqlite:///image.db', echo=True)
    meta = MetaData()

    img = Table(
        'img', meta,
        Column('id', Integer, primary_key=True),
        Column('imagecode', LargeBinary),  # 用LargeBinary对应BLOB类型
    )
    meta.create_all(engine)

    # 存储
    with engine.connect() as conn:
        conn.execute(img.insert().values(imagecode=encoding.tobytes()))

    # 恢复
    with engine.connect() as conn:
        result = conn.execute(img.select().where(img.c.id == 1)).fetchone()
        if result:
            original_encoding = np.frombuffer(result.imagecode, dtype=np.float64)
            print(original_encoding)

你的原有代码问题说明

看你提供的两段代码,还有几个小错误需要注意:

  1. 第一段SQLAlchemy代码:创建的表是img,但插入时用的是students表,表名不匹配;而且把imagecode设为String类型,直接传入numpy数组列表,导致存储的是对象的字符串表示,不是有效数据。
  2. 第二段原生SQLite代码:创建的表是img,插入时用的是image表,表名不匹配;而且传入参数时用了(x),这是列表本身,应该用(x[0],)(取第一个编码数组),否则会触发参数数量不匹配的错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.08 10:27:53