Moj*_*imi 6 python python-asyncio python-3.7 quart asgi
我仍然对asyncio如何工作感到困惑,所以我试图设置一个简单的例子但是无法实现它.
以下示例是一个Web服务器(Quart),它接收生成大型PDF的请求,然后服务器在开始处理PDF之前返回响应,然后开始处理它,并稍后将下载链接发送到电子邮件.
from quart import Quart
import asyncio
import time
app = Quart(__name__)
@app.route('/')
async def pdf():
t1 = time.time()
await generatePdf()
return 'Time to execute : {} seconds'.format(time.time() - t1)
async def generatePdf():
await asyncio.sleep(5)
#sync generatepdf
#send pdf link to email
app.run()
Run Code Online (Sandbox Code Playgroud)
我该怎么做?在上面的例子中,我不希望在返回之前等待5秒.
我甚至不确定asyncio是否是我需要的.
我担心在响应返回后阻止服务器应用程序不是应该做的事情,但也不确定.
此外,pdf库是同步的,但我想这是另一天的问题......
评论包含您响应Web请求和安排pdf生成所需的一切.
asyncio.create_task(generatePdf())
Run Code Online (Sandbox Code Playgroud)
但是,如果pdf处理速度很慢,因为它会阻止asyncio事件线程,这不是一个好主意.即当前请求将快速响应,但以下请求必须等到pdf生成完成.
正确的方法是在执行程序中运行任务(尤其是ProcessPoolExecutor).
from quart import Quart
import asyncio
import time
from concurrent.futures import ProcessPoolExecutor
app = Quart(__name__)
executor = ProcessPoolExecutor(max_workers=5)
@app.route('/')
async def pdf():
t1 = time.time()
asyncio.get_running_loop().run_in_executor(executor, generatePdf)
# await generatePdf()
return 'Time to execute : {} seconds'.format(time.time() - t1)
def generatePdf():
#sync generatepdf
#send pdf link to email
app.run()
Run Code Online (Sandbox Code Playgroud)
需要注意的是,由于它在不同的进程中运行,generatePdf
因此无法在不同步的情况下访问任何数据.因此在调用函数时传递函数所需的所有内容.
更新
如果您可以重构该generatePdf
函数并使其异步,则效果最佳.
示例如果生成pdf看起来像
def generatePdf():
image1 = downloadImage(image1Url)
image2 = downloadImage(image2Url)
data = queryData()
pdfFile = makePdf(image1, image2, data)
link = upLoadToS3(pdfFile)
sendEmail(link)
Run Code Online (Sandbox Code Playgroud)
您可以使函数async像:
async def generatePdf():
image1, image2, data = await asyncio.gather(downloadImage(image1Url), downloadImage(image2Url), queryData())
pdfFile = makePdf(image1, image2, data)
link = await upLoadToS3(pdfFile)
await sendEmail(link)
Run Code Online (Sandbox Code Playgroud)
注意:所有辅助功能,如downloadImage
,queryData
需要重写以支持async
.这样,即使数据库或映像服务器速度很慢,也不会阻止请求.一切都在同一个asyncio线程中运行.
如果其中一些还没有异步,那些可以run_in_executor
与其他异步函数一起使用并且应该可以正常工作.