Python操作SQLite报错:int()无效字面量,求代码排查帮助
首先,你的核心报错ValueError: invalid literal for int() with base 10: "SELECT AVG(rssi)..."是因为你把SQL查询语句的字符串直接赋值给了numpy数组元素,而不是执行这个查询并获取计算后的平均值。下面我会一步步拆解你的代码问题,并给出修正方案:
主要问题分析
1. 未执行SQL查询就赋值
你当前的代码只是构造了query这个字符串,并没有让数据库执行它,就直接把字符串塞给了avg[0]——数组期望的是数值,而你给了一段SQL文本,自然会报错。你需要执行查询,然后提取返回的平均值。
2. SQL拼接错误(参数未正确传递)
用format('dev', 'mac', ...)拼接SQL时,你传入的是字符串'dev'和'mac',而不是循环中的变量dev和mac的值。这会导致SQL语句变成dev LIKE 'dev',而不是匹配实际的设备编号和MAC地址,完全不符合你的需求。而且这种拼接方式存在SQL注入风险,应该用SQLite的参数化查询(用?占位符)。
3. 游标只能遍历一次
posconn.execute("SELECT distinct(mac) FROM unitedata;")返回的游标对象只能被遍历一次,你直接放在for mac in uniqmac:里,第一次循环后游标就空了,后续循环不会有数据。需要先把结果转换成列表保存。
4. executemany使用错误
executemany是用来批量插入多条数据的,而你每次只准备了一条数据,应该用execute;而且store是一个列表,并没有fetchall()方法,这会导致另一个错误。
5. 数据库连接与资源管理问题
你没有正确关闭游标和连接,最好使用with语句来自动管理数据库连接,避免资源泄漏。另外,close(avgcon)的写法错误,应该是avgcon.close()。
6. 变量名冲突
time是Python的内置模块名称,不要用它作为变量名,否则会覆盖内置模块,导致后续可能出现奇怪的问题。
修正后的代码
import sqlfunktion import numpy as np from sqlite3 import connect from datetime import datetime from time import mktime def avgrssi(date): # date on format as "YYYY,mm,dd" # 用with语句管理数据库连接,自动关闭 with sqlfunktion.opendb("totdata") as posconn: # 先把distinct mac的结果存成列表,避免游标只能遍历一次 uniqmac_cursor = posconn.execute("SELECT distinct(mac) FROM unitedata;") uniqmac_list = [row[0] for row in uniqmac_cursor.fetchall()] unixnr_cursor = posconn.execute("SELECT MIN(time) FROM unitedata;") unix = unixnr_cursor.fetchone()[0] devices = [146, 147, 148, 149] # 处理平均数据的数据库连接 with sqlfunktion.createdb("avgdata") as avgcon: # 先检查表是否存在,避免重复创建报错 avgcon.execute(""" CREATE TABLE IF NOT EXISTS avgrs( time INTEGER, mac TEXT, avg1 REAL, avg2 REAL, avg3 REAL, avg4 REAL ); """) # 遍历时间区间 for dtime in range(10 + int(unix/60), 23*60 + int(unix/60)): for mac in uniqmac_list: avg = [0.0, 0.0, 0.0, 0.0] # 用普通列表即可,numpy不是必须的 for idx, dev in enumerate(devices): # 使用参数化查询,避免SQL注入和拼接错误 query = """ SELECT AVG(rssi) FROM unitedata WHERE dev = ? AND mac = ? AND time <= ? AND time >= ?; """ # 执行查询并获取结果 cursor = avgcon.execute(query, (dev, mac, dtime*60+15, dtime*60-15)) result = cursor.fetchone()[0] # 如果有结果(不是None),就赋值,否则保持0.0 if result is not None: avg[idx] = float(result) # 插入单条数据,用execute而不是executemany current_time = dtime * 60 # 这里用明确的时间变量,避免和内置time冲突 avgcon.execute(""" INSERT INTO avgrs(time, mac, avg1, avg2, avg3, avg4) VALUES (?, ?, ?, ?, ?, ?); """, (current_time, mac, avg[0], avg[1], avg[2], avg[3])) # 获取所有平均数据 avgtab_cursor = avgcon.execute("SELECT time, mac, avg1, avg2, avg3, avg4 FROM avgrs;") avgtab = avgtab_cursor.fetchall() return avgtab if __name__ == '__main__': dato = (2018,1,5) avgrssi(dato)
关键修改说明
- 执行SQL查询并获取结果:对每个设备构造参数化查询,执行后用
fetchone()[0]获取平均值,转成浮点数后赋值给列表元素。 - 参数化SQL:用
?作为占位符,把变量作为元组传给execute,既避免了拼接错误,又防止SQL注入。 - 保存MAC列表:把游标结果转换成列表,确保可以多次遍历。
- 修改表结构:把原来的
avg列拆分成四个列(对应四个设备),这样更符合数据存储逻辑,也避免存数组的麻烦。 - 用
with管理连接:自动处理连接的打开和关闭,避免资源泄漏。 - 替换冲突变量名:把
time变量改成current_time,避免覆盖内置模块。 - 检查表是否存在:用
CREATE TABLE IF NOT EXISTS,避免重复运行时报错。
内容的提问来源于stack exchange,提问作者Sophie Green

