Flask使用AsyncHTMLSession报错signal only works in main thread咨询
问题修复方案
错误根本原因
- 报错来自
requests-html依赖的底层渲染库pyppeteer:pyppeteer初始化时会默认尝试注册SIGINT信号处理逻辑,而信号操作仅允许在主解释器的主线程中执行 - Flask 2.0+的异步视图默认运行在子线程/子解释器上下文中,不满足信号操作的权限要求,单独运行爬取脚本时是在主线程执行,因此不会触发报错
- Windows系统本身对POSIX信号的支持存在天然缺陷,进一步放大了该问题
无需引入任务队列的直接修复方案
方案1:禁用pyppeteer信号注册(优先推荐)
arender()方法支持透传参数给底层的pyppeteer启动方法,直接添加handle_sigint=False参数即可关闭信号注册逻辑,代码修改如下:
# 原代码 await r.html.arender(你的原有参数) # 修改后代码 await r.html.arender(handle_sigint=False, 你的原有参数)
该方案对原有业务逻辑侵入最小,Windows环境下直接生效。
方案2:调整Flask运行模式(适合开发测试场景)
如果方案1不生效,可调整ASGI服务器的运行配置,让所有请求逻辑都运行在主解释器的主线程中:
- 若使用uvicorn启动Flask,执行命令:
uvicorn 你的启动文件:app --workers 1 --threads 1 - 若使用werkzeug开发服务器,启动时添加参数:
app.run(threaded=False)
注意该方案会降低服务并发能力,仅适合并发量低的小型场景使用。
什么时候需要引入任务队列
如果满足以下任意场景,才建议引入Celery、RQ等任务队列组件:
- 单次爬取任务耗时超过30秒,会导致HTTP请求超时
- 存在多用户同时触发爬取的高并发需求
- 需要支持爬取进度查询、失败重试等高级特性
如果只是低频次、短耗时的爬取需求,上述两种修复方案完全可以满足需求,不需要额外引入任务队列增加架构复杂度。
内容的提问来源于stack exchange,提问作者PythonJohn
相关产品推荐
相关产品推荐

