Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django asyncio call in views doesn't work

I'm struggling on this problem for quite a moment now. I'm trying to export a view in pdf, using pyppeteer. Here are my functions :

  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

And call it like that in my view:

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

But I got this error

RuntimeError at /export-pdf/1/2018/1/1/ There is no current event loop in thread 'Thread-1'.

After some research I thought someone solved my problem and I called it like that (didn't quite understand, but it's something about django and my function not called in the main thread):

  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()

But now I have this error :

TypeError at /export-pdf/1/2018/1/1/ expect a list of futures, not coroutine

I'm quite new to async in python, and the thing is, when i copy and paste the exact same code in my ipython shell, everything works fine.

Any explanation / light would be appreciated !

Thanks in advance.

EDIT : After some research i've managed to come to another error, which is

signal only works in main thread

The weird thing is that the error come from /usr/lib/python3.6/signal.py which is not even from my virtualenv.

like image 871
Bestasttung Avatar asked Apr 04 '18 09:04

Bestasttung


1 Answers

your approach is the right one, except that there is an extra asyncio.wait call. Simply do:

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
like image 119
Arthur Avatar answered Oct 23 '22 08:10

Arthur