如何将sqlite3模块转为asyncio非阻塞模式及协程转游标问题
解决sqlite3结合asyncio异步改造的AttributeError问题
首先得戳破两个核心问题:
- 标准库的
sqlite3是纯同步库,完全不支持asyncio的异步上下文管理器(async with),你写的GetCursor_Async里的async with sqlite3.connect(...)其实是无效写法;而且异步方法调用后必须用await才能拿到实际结果,不然得到的就是coroutine对象——这就是你触发AttributeError的直接原因。 - 同步的游标对象本身就是阻塞式的,就算你拿到了,在异步代码里用它也违背了asyncio的异步逻辑,根本达不到非阻塞的目的。
正确改造方案:用异步SQLite库aiosqlite
标准库没提供异步SQLite支持,我们得用专门为asyncio设计的第三方库aiosqlite,先安装它:
pip install aiosqlite
修改后的完整代码
# -*- coding: utf-8 -*- # sqlite01.py import os import asyncio import aiosqlite class SQLite(): def __init__(self, DB='./static/Clientes.db'): print("sqlite01>Current Directory:%s" % os.getcwd()) self.DB = DB # 保留原同步方法(兼容旧代码) def GetCursor(self): import sqlite3 with sqlite3.connect(self.DB) as db: return db.cursor() # 异步获取游标(aiosqlite的正确用法) async def GetCursor_Async(self): db = await aiosqlite.connect(self.DB) return await db.cursor() # 同步版CreateHTML(兼容旧逻辑) def CreateHTML(self, CURSOR, OPT=None): para = [] for row in CURSOR.execute('''SELECT * FROM cliente ORDER BY nome'''): para.append(f"<option value=\"{row[0]}\">{row[0]}</option>") return para # 异步版CreateHTML(配合异步游标) async def CreateHTML_Async(self, CURSOR, OPT=None): para = [] # aiosqlite的execute是异步方法,必须await await CURSOR.execute('''SELECT * FROM cliente ORDER BY nome''') rows = await CURSOR.fetchall() for row in rows: para.append(f"<option value=\"{row[0]}\">{row[0]}</option>") return para
正确的异步测试代码
异步方法必须在async函数/上下文里调用,测试代码要这么写:
import sqlite01 import asyncio async def main(): SQL = sqlite01.SQLite() # 异步获取游标必须加await cursor = await SQL.GetCursor_Async() # 调用异步版CreateHTML也得await result = await SQL.CreateHTML_Async(cursor) print(type(result)) # 输出 <class 'list'> print(result) # 启动异步事件循环 asyncio.run(main())
关键细节提醒
- aiosqlite的核心特性:它所有数据库操作(连接、游标创建、execute、fetch)都是异步方法,完全适配asyncio事件循环,不会阻塞其他任务。
- await的必要性:所有
async修饰的方法,调用时必须加await才能拿到实际返回值,否则只会得到一个未执行的coroutine对象。 - 游标操作的异步差异:aiosqlite的游标不能像同步库那样直接迭代
execute结果,必须先await execute(),再用await fetchall()/await fetchone()获取数据。
内容的提问来源于stack exchange,提问作者DevBush
相关产品推荐
相关产品推荐

