8

我现在在这个问题上挣扎了很长时间。我正在尝试使用pyppeteer以 pdf 格式导出视图。这是我的功能:

  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

在我看来,这样称呼它:

   response.content = asyncio.get_event_loop().run_until_complete(
      export_pdf(self.request.get_full_path())
  )

但我得到了这个错误

/export-pdf/1/2018/1/1/ 处的 RuntimeError 线程“Thread-1”中没有当前事件循环。

经过一番研究,我认为有人解决了我的问题,我这样称呼它(不太明白,但这是关于 django 的事情,我的函数没有在主线程中调用):

  loop = asyncio.new_event_loop()
  asyncio.set_event_loop(loop)
  response.content = loop.run_until_complete(
      export_pdf(
          asyncio.wait(
              export_pdf(self.request.get_full_path())
          )
      )
  )
  loop.close()

但现在我有这个错误:

/export-pdf/1/2018/1/1/ 的 TypeError 期望期货列表,而不是协程

我对 python 中的 async 很陌生,问题是,当我在 ipython shell 中复制并粘贴完全相同的代码时,一切正常。

任何解释/灯光将不胜感激!

提前致谢。

编辑: 经过一些研究,我设法遇到了另一个错误,即

信号仅在主线程中有效

奇怪的是,错误/usr/lib/python3.6/signal.py甚至不是来自我的virtualenv。

4

3 回答 3

4

你的方法是正确的,除了有一个额外的asyncio.wait电话。只需这样做:

coroutine = export_pdf(self.request.get_full_path())

# nothing is done yet, we need to give this coroutine to an event loop which will run it
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
try:
   data = loop.run_until_complete(coroutine)
finally:
    loop.close()

response.content = data
于 2018-04-04T16:20:11.060 回答
0

我试图做和你一样的事情。但是,我没有用线程来搞乱我的 Django 服务器,而是听从 Arthur 的建议,而是决定使用我自己的 Puppeteer 微服务。

但是在这个过程的中间,我发现有人有同样的想法,并为此创建了一个准备部署的工具:https ://github.com/alvarcarto/url-to-pdf-api

基本上,您只需要部署此代码(如果您使用 Heroku,则单击按钮),然后使用您的应用程序的 url 开始生成 pdf。

于 2018-10-10T12:02:30.970 回答
0

也许将其作为 celery 任务执行,并在调用 celery 任务时使用 apply_async 。这可能会有所帮助:https ://www.youtube.com/watch?v=XjzyOyLbvN8

于 2018-04-05T13:28:28.597 回答