资讯详情

Python sqlite3 游标使用方法:TaoToken 统一 Key 接入与 settings.json 配置骨架

📅 2026/9/29 4:17:21 | 华诺云谱 👁 阅读
Python sqlite3 游标使用方法:TaoToken 统一 Key 接入与 settings.json 配置骨架
1. Python sqlite3 游标到底在做什么如果你写过conn.execute(select ...)就直接拿结果可能没意识到背后其实已经隐式创建了一个游标。sqlite3的游标Cursor是连接对象和 SQL 语句之间的执行通道它负责把 SQL 发给数据库、维护结果集的位置、再把行按需吐给你。理解游标本质上是理解「结果集是有状态的」这件事。游标最容易被忽略的特性是它像迭代器一样只能往前走fetchone()取一行就少一行fetchall()取完之后再取就是空列表。很多人第一次踩坑就是先fetchone()探一下有没有数据然后再fetchall()结果发现只剩后面几行。这不是 bug是游标的位置被消耗了。这篇面向的是本地脚本或小型服务场景你用 Python 的sqlite3做增删改查同时希望通过统一的 Key/API 通道调用模型来辅助生成 SQL、补全游标逻辑、排查报错。我会把settings.json配置骨架、游标验证脚本、连通性验证动作串成一条可复制的链路让你一次跑通。适合谁写过一点 Python、知道import sqlite3但游标用得不够顺手的开发者或者想把模型调用配置从代码里抽出来、统一走一个入口的工程化需求。下面所有代码都可以直接粘贴运行配置项按你的实际环境替换即可。2. 统一 Key 接入的前置准备把模型调用配置写死在代码里换环境就要改代码这是小型项目最常见的维护痛点。更稳的做法是抽一个settings.json把 base_url、api_key、模型名、超时这些放进去代码只读配置。这样本地脚本、CI、小服务可以共用同一套骨架只换配置文件。统一接入的地址我用 TaoToken 这套官网入口是 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content API 基址是 https://taotoken.net/api 。注意 API 地址不带 UTM 参数配置里写干净的 base_url 就行。Key 的获取在控制台的 API Keys 页面https://taotoken.net/console/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi_keysutm_campaignrewrite 接入文档在 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 。这里要区分两个概念sqlite3的游标是本地数据库操作模型调用是另一条网络链路。两者不冲突但配置要分开管理。我建议settings.json里用database和llm两个顶层键数据库部分放文件路径和超时模型部分放 base_url、api_key、model、timeout。这样你调试游标逻辑时不会因为模型配置写错而整个脚本起不来。一个实际经验不要把 api_key 提交进 git。settings.json可以提交一个settings.example.json真实文件加进.gitignore或者用环境变量覆盖。下面骨架里我会用api_key_env字段支持从环境变量读取兼顾方便和安全。3. settings.json 配置骨架与游标脚本先给配置骨架。字段命名尽量直白方便你和团队其他人一眼看懂。database.path是 sqlite 文件路径:memory:表示内存库适合测试。llm.base_url固定写 API 基址llm.api_key_env指向环境变量名代码运行时读取。{ database: { path: app.db, timeout: 5.0, detect_types: false }, llm: { base_url: https://taotoken.net/api, api_key_env: TAOTOKEN_API_KEY, model: claude-sonnet-4-20250514, timeout: 30, max_tokens: 1024 }, app: { table: catalog, log_level: INFO } }读取配置和建立连接的代码。注意sqlite3.connect的timeout参数控制的是锁等待时间不是查询超时别混淆。row_factory设成sqlite3.Row之后游标取出来的行可以按列名访问比纯 tuple 好用很多这是游标使用里性价比最高的一个设置。import json import os import sqlite3 def load_settings(pathsettings.json): with open(path, r, encodingutf-8) as f: return json.load(f) def get_connection(cfg): db cfg[database] conn sqlite3.connect(db[path], timeoutdb.get(timeout, 5.0)) conn.row_factory sqlite3.Row return conn def get_api_key(cfg): env_name cfg[llm][api_key_env] key os.environ.get(env_name) if not key: raise RuntimeError(f环境变量 {env_name} 未设置) return key接下来是游标的核心操作。建表、插入、查询、更新、删除每一步都用显式游标方便你观察状态变化。executemany批量插入比循环execute快很多数据量大时差别明显。def init_table(conn, table): cur conn.cursor() cur.execute(f create table if not exists {table} ( id integer primary key, pid integer, name varchar(32) unique ) ) conn.commit() cur.close() def insert_rows(conn, table, rows): cur conn.cursor() cur.executemany( finsert or ignore into {table} (id, pid, name) values (?, ?, ?), rows ) conn.commit() print(f插入影响行数: {cur.rowcount}) cur.close() def query_all(conn, table): cur conn.cursor() cur.execute(fselect id, pid, name from {table} order by id) rows cur.fetchall() cur.close() return rows游标的状态特性用一个对比脚本演示最清楚。下面这段先fetchone()再fetchall()你会看到fetchall只剩后面的行因为游标位置已经前移了。想重新从头取必须重新execute。def demo_cursor_state(conn, table): cur conn.cursor() cur.execute(fselect id, name from {table} order by id) first cur.fetchone() print(fetchone:, dict(first) if first else None) rest cur.fetchall() print(fetchall 剩余:, [dict(r) for r in rest]) cur.close() cur2 conn.cursor() cur2.execute(fselect id, name from {table} order by id) print(重新 execute 后 fetchall:, [dict(r) for r in cur2.fetchall()]) cur2.close()更新和删除同样走游标重点是commit()的时机。sqlite3默认在 DML 语句前自动开事务你不 commit改动只在当前连接可见别的连接读不到程序异常退出还会回滚。小型服务里我习惯每次写操作后立即 commit而不是攒到关闭时统一提交。def update_row(conn, table, row_id, new_name): cur conn.cursor() cur.execute(fupdate {table} set name ? where id ?, (new_name, row_id)) conn.commit() print(f更新影响行数: {cur.rowcount}) cur.close() def delete_row(conn, table, row_id): cur conn.cursor() cur.execute(fdelete from {table} where id ?, (row_id,)) conn.commit() print(f删除影响行数: {cur.rowcount}) cur.close()把上面拼起来跑一遍你就有了一个完整的游标操作闭环。参数化查询用?占位符不要用字符串拼接这是防注入的基本功也是游标execute第二个参数存在的意义。4. 连通性验证与成功结果配置和脚本都有了先验证模型通道能不能通。用requests发一个最小请求确认 base_url 和 key 都正确。这一步和 sqlite 无关但它是你后续用模型辅助生成 SQL 的前提。import requests def verify_llm(cfg): key get_api_key(cfg) url cfg[llm][base_url].rstrip(/) /v1/messages headers { x-api-key: key, anthropic-version: 2023-06-01, content-type: application/json, } payload { model: cfg[llm][model], max_tokens: 64, messages: [ {role: user, content: 只回复两个字连通} ], } resp requests.post(url, headersheaders, jsonpayload, timeoutcfg[llm][timeout]) print(状态码:, resp.status_code) print(响应:, resp.text[:300]) return resp.status_code 200跑通后你会看到状态码 200响应体里包含模型返回的文本。如果返回 401检查环境变量是否设置、key 是否复制完整返回 404 通常是 base_url 拼错注意不要重复加/v1。再验证 sqlite 游标链路。下面这段把配置加载、建表、插入、查询、状态演示、更新、删除串起来直接运行看输出。if __name__ __main__: cfg load_settings() conn get_connection(cfg) table cfg[app][table] init_table(conn, table) insert_rows(conn, table, [(0, 0, name1), (1, 0, name2), (2, 0, name3)]) print(全量查询:, [dict(r) for r in query_all(conn, table)]) demo_cursor_state(conn, table) update_row(conn, table, 0, name1_updated) delete_row(conn, table, 2) print(最终数据:, [dict(r) for r in query_all(conn, table)]) conn.close()预期输出大致是插入影响行数 3全量查询三行fetchone返回第一行fetchall只剩两行重新 execute 后又是三行更新影响行数 1删除影响行数 1最终数据两行。看到这个结果说明游标的状态行为和你的预期一致了。如果你想让模型帮你生成复杂 SQL可以把表结构和需求描述发给模型走同一个verify_llm里的通道。模型对话入口在 https://taotoken.net/chat?utm_sourcetaotoken_aicg_blog_endutm_contentchatutm_campaignrewrite 适合快速试 prompt长期写代码、跑 Agent 的场景更适合 Coding Planhttps://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding_planutm_campaignrewrite 。5. 本篇常见错排查游标取完数据为空。最常见的原因是同一个游标先fetchone再fetchall或者循环里重复fetchall。游标位置只前进不后退取完就没了。解决方式是每次查询重新execute或者用fetchmany(n)分批取。忘记 commit 导致数据丢失。插入、更新、删除之后没commit程序正常退出时sqlite3会回滚未提交事务。表现是脚本里查得到重开连接就没了。养成写操作后立即 commit 的习惯或者用with conn:上下文管理器自动提交。rowcount对 select 返回 -1。rowcount只对 DML 语句有意义select 之后它不可靠。想知道查询返回多少行用len(cur.fetchall())但注意这会消耗游标。多线程共用连接报错。sqlite3连接默认不能跨线程使用会抛ProgrammingError。小型服务里要么每个线程独立连接要么用连接池要么加锁串行化。别图省事全局共享一个 conn。参数化查询写成字符串拼接。cur.execute(fselect * from t where id {x})这种写法既有注入风险遇到字符串类型还会因为引号报错。统一用?占位符加元组参数。模型调用返回 401 或 403。先确认环境变量名和settings.json里的api_key_env一致再确认 key 没有多余空格。如果用的是控制台新建的 key注意有些 key 只在创建时显示一次。接入文档里有完整的鉴权说明https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 。base_url 拼接重复路径。https://taotoken.net/api后面接/v1/messages是完整路径不要再手动加一层/api。建议在代码里用rstrip(/)统一处理尾部斜杠。6. 把配置和游标固化成项目习惯跑通之后建议把settings.json的读取封装成一个模块所有脚本都从它拿配置而不是各自open文件。游标操作也封装成小函数比如query_all、insert_rows调用方不直接碰conn.cursor()。这样换数据库、换模型通道时改动集中在一处。Key 的管理走控制台https://taotoken.net/console/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi_keysutm_campaignrewrite 需要轮换或新增时在这里操作代码侧只改环境变量。API 基址保持 https://taotoken.net/api 不变配置骨架里的base_url就不用动。最后留一个实用技巧调试游标逻辑时把conn.row_factory设成sqlite3.Row打印时用dict(row)转一下输出比裸 tuple 可读得多。等逻辑稳定了再考虑性能优化比如批量操作用executemany、只读查询用fetchmany控制内存。游标本身不复杂难的是记住它是有状态的每次取数据前想一下「游标现在在哪」。
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。

↑