Pyppeteer与Quart结合出现Event loop is closed错误求助
解决Quart + Pyppeteer中"Event loop is closed"的清理问题
你的问题根源在于用同步的atexit钩子去处理异步清理操作,而Quart作为异步Web框架,在停止时会先关闭事件循环,之后atexit的同步函数再去调用run_until_complete就会触发"Event loop is closed"错误。另外,全局直接用run_until_complete启动浏览器也不符合Quart的异步生命周期规范。
正确的做法是利用Quart提供的异步生命周期钩子,在框架启动前初始化浏览器,在框架停止后(事件循环仍运行时)清理浏览器实例,完全贴合异步环境的执行逻辑。
修正后的代码示例
#!/usr/bin/env python3 import pyppeteer from quart import Quart, Response, request app = Quart(__name__) browser = None # 先初始化空变量,后续在钩子中赋值 # 在Quart启动服务前初始化浏览器 @app.before_serving async def startup(): global browser browser = await pyppeteer.launch() # 在Quart停止服务后清理浏览器 @app.after_serving async def cleanup(): await browser.quit() # 示例路由,使用浏览器实例 @app.route('/') async def index(): page = await browser.newPage() await page.goto('https://example.com') content = await page.content() await page.close() return Response(content, mimetype='text/html') if __name__ == '__main__': app.run(host='0.0.0.0')
为什么这个方案可行?
@app.before_serving:这个钩子会在Quart的事件循环启动后、开始处理请求前执行异步代码,确保浏览器在正确的异步环境中初始化,不需要手动调用run_until_complete。@app.after_serving:这个钩子会在Quart停止接收请求后、事件循环关闭前执行异步清理操作,此时事件循环仍处于运行状态,await browser.quit()可以正常执行,不会出现"Event loop is closed"的错误。- 完全避免了同步/异步代码的冲突,贴合Quart的异步设计理念。
额外优化建议
如果需要全局管理浏览器实例的并发访问,可以添加一个异步锁(asyncio.Lock)来避免多个请求同时操作浏览器导致的问题:
import asyncio # 在全局添加异步锁 browser_lock = asyncio.Lock() @app.route('/') async def index(): async with browser_lock: # 确保同一时间只有一个请求操作浏览器 page = await browser.newPage() await page.goto('https://example.com') content = await page.content() await page.close() return Response(content, mimetype='text/html')
内容的提问来源于stack exchange,提问作者d33tah
相关产品推荐
相关产品推荐

