我还是如何ASYNCIO作品很迷茫,所以我想设置一个简单的例子,但未能实现。
下面的例子是接收产生大量PDF的请求的Web服务器(夸脱),然后服务器会返回处理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()
我将如何去吗?在上面的例子中,我不希望5秒回前等待。
我甚至不知道ASYNCIO正是我需要的。
而且恐怕阻塞服务器应用程序的响应返回之后是不应该做的事情,但也不清楚。
另外,PDF库是同步的,但我想这是另一天的问题...
注释有你需要的响应web请求,并安排PDF生成供以后的一切。
asyncio.create_task(generatePdf())
但是它不是如果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()
需要注意的是,因为它是在不同的进程中运行,该generatePdf
不能没有同步访问任何数据是非常重要的。所以,一切都通过调用函数时,函数需要。
更新
如果你能重构generatePdf
功能,使之异步,它的效果最好。
的生成PDF的例子,类似于
def generatePdf():
image1 = downloadImage(image1Url)
image2 = downloadImage(image2Url)
data = queryData()
pdfFile = makePdf(image1, image2, data)
link = upLoadToS3(pdfFile)
sendEmail(link)
您可以使异步功能,如:
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)
注:所有喜欢downloadImage
的辅助功能,queryData
需要重写以支持async
。通过这种方式,请求将得不到即使数据库或图像服务器慢阻塞。一切都在同一ASYNCIO线程中运行。
如果他们中的一些尚未异步,那些可以用run_in_executor
使用,并应工作好与其他异步功能。
对于你的任务,产生较大的PDF,你可以使用一个异步任务/作业队列。举个例子,你可以使用Celery。既然你不想等待任务,而返回希望得到答复 - “生成PDF,请等待一分钟/秒”。所以,当一个请求到达“生成PDF”端点,您将芹菜中创建一个任务,芹菜会异步处理,并完成后,你可以推到客户端或客户端可以使用“任务查找”使用任务ID(或者当你实现)。下面是一个例子答案 - How to check task status in Celery?
芹菜和ASYNCIO之间的区别是,芹菜可在完全分离的环境中执行一个任务,并与服务器的通信是通过使像RabbitMQ一个分布式消息来完成。凡ASYNCIO使用协同程序利用阻塞I / O时间。它会使用相同的环境和你服务器所在的处理器。