视图中的 Django asyncio 调用不起作用
Django asyncio call in views doesn't work
我在这个问题上纠结了好久。
我正在尝试使用 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())
)
但是我遇到了这个错误
RuntimeError at /export-pdf/1/2018/1/1/
There is no current event loop in thread '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()
但是现在我有这个错误:
TypeError at /export-pdf/1/2018/1/1/
expect a list of futures, not coroutine
我对 python 中的异步还很陌生,问题是,当我在 ipython shell 中复制并粘贴完全相同的代码时,一切正常。
任何解释/光线将不胜感激!
提前致谢。
编辑:
经过一些研究,我设法遇到了另一个错误,即
signal only works in main thread
奇怪的是错误来自 /usr/lib/python3.6/signal.py
而不是来自我的 virtualenv。
你的方法是正确的,除了有一个额外的 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
也许可以将其作为 celery 任务执行,并在调用 celery 任务时使用 apply_async。这可能有帮助:https://www.youtube.com/watch?v=XjzyOyLbvN8
我正在尝试做与您完全相同的事情。
但是,我没有按照 Arthur 的建议用线程搞乱我的 Django 服务器,而是决定使用我自己的 Puppeteer 微服务。
但是在这个过程中,我发现有人有同样的想法并为此创建了一个准备部署的工具:https://github.com/alvarcarto/url-to-pdf-api
基本上,您只需要部署此代码(如果您使用的是 Heroku,则只需单击按钮),然后使用您应用的 url 开始生成 pdf。
我在这个问题上纠结了好久。 我正在尝试使用 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())
)
但是我遇到了这个错误
RuntimeError at /export-pdf/1/2018/1/1/ There is no current event loop in thread '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()
但是现在我有这个错误:
TypeError at /export-pdf/1/2018/1/1/ expect a list of futures, not coroutine
我对 python 中的异步还很陌生,问题是,当我在 ipython shell 中复制并粘贴完全相同的代码时,一切正常。
任何解释/光线将不胜感激!
提前致谢。
编辑: 经过一些研究,我设法遇到了另一个错误,即
signal only works in main thread
奇怪的是错误来自 /usr/lib/python3.6/signal.py
而不是来自我的 virtualenv。
你的方法是正确的,除了有一个额外的 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
也许可以将其作为 celery 任务执行,并在调用 celery 任务时使用 apply_async。这可能有帮助:https://www.youtube.com/watch?v=XjzyOyLbvN8
我正在尝试做与您完全相同的事情。 但是,我没有按照 Arthur 的建议用线程搞乱我的 Django 服务器,而是决定使用我自己的 Puppeteer 微服务。
但是在这个过程中,我发现有人有同样的想法并为此创建了一个准备部署的工具:https://github.com/alvarcarto/url-to-pdf-api
基本上,您只需要部署此代码(如果您使用的是 Heroku,则只需单击按钮),然后使用您应用的 url 开始生成 pdf。