在Django中用pyppeteer生成PDF报错:信号仅在主解释器主线程生效
解决Django中使用pyppeteer生成PDF的报错问题
问题分析
你遇到的两个错误本质是Django线程模型与pyppeteer异步运行机制的冲突:
signal only works in main thread of the main interpreter:pyppeteer启动浏览器时需要处理系统信号,而Django的请求处理线程并非主线程,信号只能在主线程中处理,因此触发该错误。This event loop is already running:尝试在Django线程中手动调用run_until_complete时,该线程可能已存在活跃事件循环,导致重复运行报错。
解决方案
将pyppeteer的异步任务放到独立线程中执行,让该线程成为自身主线程以处理信号,同时避免与Django的事件循环冲突。修改后的views.py代码如下:
from pyppeteer import launch import asyncio from threading import Thread from django.http import HttpResponse async def main(): browser = await launch() page = await browser.newPage() await page.goto("https://python.org") await page.waitFor(1000) await page.pdf({"path": "python.pdf"}) await browser.close() def run_async_task(func): # 创建新的事件循环并运行异步任务 loop = asyncio.new_event_loop() asyncio.set_event_loop(loop) loop.run_until_complete(func()) loop.close() def generate_pdf(request): print("Starting...") # 在独立线程中执行异步任务 thread = Thread(target=run_async_task, args=(main,)) thread.start() thread.join() print("PDF has been taken") return HttpResponse("PDF has been generated")
额外建议
生成PDF属于耗时操作,直接在请求线程中等待完成会导致请求阻塞,影响用户体验。建议使用异步任务队列(如Celery)将PDF生成任务后台化,请求仅负责触发任务并返回状态,后续再通过其他方式获取生成好的PDF文件。
内容的提问来源于stack exchange,提问作者Sudip Bhandari
相关产品推荐
相关产品推荐

