Python asyncio跳过处理直到函数返回

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库是同步的,但我想这是另一天的问题......

bal*_*lki 6

评论包含您响应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与其他异步函数一起使用并且应该可以正常工作.