使用Sanic与aiohttp时遇TypeError:'coroutine'对象不可迭代求助
解决aiohttp与Sanic配合时的"coroutine object is not iterable"错误
看起来你遇到的这个错误核心原因是异步上下文管理器的使用方式不对,直接运行函数时事件循环的调度差异掩盖了问题,但在Sanic的Web请求上下文里就触发了异常。
第一步:修复fetch函数的上下文管理器问题
你的fetch函数里用了普通的with调用async_timeout.timeout,但它是异步上下文管理器,必须使用async with才能正确工作:
async def fetch(session, url, **kwargs): async with async_timeout.timeout(10): # 将普通with改为async with async with session.get(url, **kwargs, verify_ssl=False) as response: return await response.text()
为什么会出现这个错误?
普通的with语句无法处理异步上下文管理器的协程方法,这会导致async_timeout没有正确注入超时控制逻辑,进而让后续的session.get调用在事件循环中处于异常状态,最终引发loop.create_connection返回的协程对象无法被正确迭代的错误。直接运行函数时,事件循环的调度逻辑刚好避开了这个问题,但在Sanic的请求处理流程中,这个矛盾就会被触发。
额外的优化建议
- 复用
aiohttp.ClientSession:你现在在每个爬虫函数里都创建新的ClientSession,高并发场景下会产生大量连接创建/销毁的开销,影响性能。建议在Sanic启动时创建全局会话,所有请求复用它:
import aiohttp from sanic import Sanic app = Sanic("VideoSearchApp") # 启动时创建全局ClientSession @app.listener("before_server_start") async def setup_client_session(app, loop): app.ctx.client_session = aiohttp.ClientSession(loop=loop) # 停止时关闭会话 @app.listener("after_server_stop") async def close_client_session(app, loop): await app.ctx.client_session.close() # 爬虫函数中使用全局会话 async def get_bilibili_query(keyword, page=1, order='totalrank'): base_url = "https://search.bilibili.com/all" query_params = { "keyword": keyword, "page": page, "order": order, } html = await fetch(app.ctx.client_session, url=base_url, params=query_params) # 后续解析逻辑保持不变...
- 升级依赖版本:你使用的Python3.5和对应版本的aiohttp都比较老旧,存在不少已知的事件循环兼容性问题。如果业务允许,建议升级到Python3.7+和较新的aiohttp版本(比如3.x系列),能避免很多潜在问题。
- 细化错误处理:当前爬虫函数里只是简单捕获Exception后continue,建议添加错误日志记录,方便后续调试定位具体的解析失败原因。
内容的提问来源于stack exchange,提问作者AngeloLi
相关产品推荐
相关产品推荐

