You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django视图中asyncio调用失效,Pyppeteer导出PDF遇RuntimeError

解决Pyppeteer导出PDF时触发的RuntimeError问题

嘿,我帮你捋清楚这个问题:你遇到的RuntimeError,大概率是因为在已经有活跃事件循环的线程中,又尝试用asyncio.get_event_loop().run_until_complete()启动新的事件循环导致的冲突——毕竟像Flask、Django这类Web框架的视图函数,本身可能已经运行在一个事件循环上下文里了,重复操作自然会报错。

下面给你两种针对性的解决方案,你可以根据自己的视图类型来选:

方案一:如果是异步视图(优先推荐)

如果你的Web框架支持异步视图(比如FastAPI、Django 3.1及以上版本),完全不用手动折腾事件循环,直接await你的export_pdf函数就行:

# 举个FastAPI异步视图的例子
from fastapi import FastAPI, Request, Response
from pyppeteer import launch

app = FastAPI()

async def export_pdf(url):
    browser = await launch()
    page = await browser.newPage()
    await page.goto(url)
    pdf = await page.pdf({'printBackground': True})
    await browser.close()
    return pdf

@app.get("/export-pdf")
async def pdf_export_endpoint(request: Request):
    # 生成目标页面的完整绝对URL
    target_url = request.url_for("your_target_page_endpoint")
    pdf_content = await export_pdf(str(target_url))
    return Response(content=pdf_content, media_type="application/pdf")

如果是Django的异步视图,写法类似:

async def pdf_export_view(request):
    full_url = request.build_absolute_uri()
    pdf_content = await export_pdf(full_url)
    response = HttpResponse(pdf_content, content_type='application/pdf')
    response['Content-Disposition'] = 'attachment; filename="export.pdf"'
    return response

方案二:如果必须在同步视图中调用

如果你的视图是同步的,那就需要用嵌套事件循环来解决冲突,这里可以借助nest_asyncio库:

  1. 先安装这个库:
pip install nest_asyncio
  1. 修改你的代码逻辑:
import nest_asyncio
import asyncio
from pyppeteer import launch
from django.http import HttpResponse

# 注意:把这行放在项目初始化的地方(比如Django的settings.py、Flask的启动文件),只需要执行一次
nest_asyncio.apply()

async def export_pdf(url):
    browser = await launch()
    page = await browser.newPage()
    await page.goto(url)
    pdf = await page.pdf({'printBackground': True})
    await browser.close()
    return pdf

# 同步视图中的调用方式
def sync_pdf_view(request):
    # 这里一定要用完整的绝对URL,相对路径会导致Pyppeteer导航失败
    full_url = request.build_absolute_uri()
    # 现在可以安全运行异步函数了
    pdf_content = asyncio.get_event_loop().run_until_complete(export_pdf(full_url))
    response = HttpResponse(pdf_content, content_type='application/pdf')
    response['Content-Disposition'] = 'attachment; filename="export.pdf"'
    return response

额外提醒

你之前用self.request.get_full_path()获取的是相对路径,Pyppeteer的page.goto()需要完整的绝对URL(比如http://localhost:8000/your-page),否则会导航失败,建议改成request.build_absolute_uri()来生成正确的URL哦。

内容的提问来源于stack exchange,提问作者Bestasttung

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 07:39:27