Python 使用asyncio.create_task()函数并发运行多个任务

本文介绍了Python如何使用asyncio.create_task()函数并发运行多个任务。

模拟长时间运行的操作

要模拟长时间运行的操作,可以使用asyncio包的sleep()协程。该sleep()函数延迟指定的秒数:

<span style="background-color:#f8f8f8"><span style="color:#212529"><code class="language-python"><span style="color:#f47067">await</span> asyncio.sleep(seconds)</code></span></span>

因为sleep()是协程,所以需要使用await关键字。例如,下面使用sleep()协程模拟 API 调用:

import asyncio
async def call_api(message, result=1000, delay=3):
print(message)
await asyncio.sleep(delay)
return result

call_api()是协程。它显示一条消息,暂停指定的秒数(默认为三秒),然后返回结果。

以下程序使用call_api()两次并测量完成所需的时间:

import asyncio
import time
async def call_api(message, result=1000, delay=3):
print(message)
await asyncio.sleep(delay)
return result
async def main():
start = time.perf_counter()
price = await call_api('Get stock price of GOOG...', 300)
print(price)
price = await call_api('Get stock price of APPL...', 400)
print(price)
end = time.perf_counter()
print(f'It took {round(end-start,0)} second(s) to complete.')
asyncio.run(main())

输出:

Get stock price of GOOG...
300
Get stock price of APPL...
400
It took 6.0 second(s) to complete.

首先,使用time模块的perf_counter()函数启动一个定时器来测量时间:

<span style="background-color:#f8f8f8"><span style="color:#212529"><code class="language-python"> start = time.perf_counter()</code></span></span>

二、调用call_api()协程并显示结果:

price = await call_api('Get stock price of GOOG...', 300)
print(price)

三、call_api()第二次调用:

price = await call_api('Get stock price of APPL...', 400)
print(price)

最后,显示程序完成所需的时间:

end = time.perf_counter()
print(f'It took {round(end-start,0)} second(s) to complete.')

因为每个都call_api()需要三秒钟,所以调用它两次需要六秒钟。

在这个例子中,我们直接调用了一个协程,并没有放到事件循环中去运行。相反,我们得到一个协程对象并使用await关键字来执行它并得到一个结果。

我们使用asyncandawait编写异步代码但不能并发运行,要同时运行多个操作,我们需要使用称为任务的东西。

Python 任务简介

任务是协程的包装器,它安排协程尽快在事件循环上运行。

调度和执行以非阻塞方式发生,可以创建任务并在任务运行时立即执行其他代码。

请注意,任务不同于await阻塞整个协程直到操作完成并产生结果的关键字。

重要的是可以创建多个任务并安排它们同时在事件循环中立即运行。

要创建任务,需要将协程传递给asyncio包的create_task()函数。该create_task()函数返回一个Task对象。

下面的程序说明了如何创建两个调度和执行call_api()协程的任务:

import asyncio
import time
async def call_api(message, result=1000, delay=3):
print(message)
await asyncio.sleep(delay)
return result
async def main():
start = time.perf_counter()
task_1 = asyncio.create_task(
call_api('Get stock price of GOOG...', 300)
)
task_2 = asyncio.create_task(
call_api('Get stock price of APPL...', 300)
)
price = await task_1
print(price)
price = await task_2
print(price)
end = time.perf_counter()
print(f'It took {round(end-start,0)} second(s) to complete.')
asyncio.run(main())

输出:

Get stock price of GOOG...
Get stock price of APPL...
300
300
It took 3.0 second(s) to complete.

在程序的某个时刻使用 await 关键字来等待任务是很重要的。

如果我们不使用 await 关键字,Python 会安排任务运行但在asyncio.run()关闭事件循环时停止它。

下图说明了程序的执行流程:

最后,显示完成该main()函数所需的时间:

end = time.perf_counter()
print(f'It took {round(end-start,0)} second(s) to complete.')

通过使用该create_task()函数,该程序要快得多。运行的任务越多,速度就越快。

等待时运行其他任务

当 call_api 运行时,可以运行其他任务。例如,以下程序在等待 call_api 任务时每秒显示一条消息:

import asyncio
import time
async def call_api(message, result=1000, delay=3):
print(message)
await asyncio.sleep(delay)
return result
async def show_message():
for _ in range(3):
await asyncio.sleep(1)
print('API call is in progress...')
async def main():
start = time.perf_counter()
message_task = asyncio.create_task(
show_message()
)
task_1 = asyncio.create_task(
call_api('Get stock price of GOOG...', 300)
)
task_2 = asyncio.create_task(
call_api('Get stock price of APPL...', 300)
)
price = await task_1
print(price)
price = await task_2
print(price)
await message_task
end = time.perf_counter()
print(f'It took {round(end-start,0)} second(s) to complete.')
asyncio.run(main())

输出:

Get stock price of GOOG...
Get stock price of APPL...
API call is in progress...
API call is in progress...
API call is in progress...
300
300

总结

  • 任务是协程的包装器,它安排协程尽快在事件循环上运行。
  • 使用asyncio库的create_task()函数创建任务。
  • 在程序中的某个时刻将await关键字与任务一起使用,以便可以在asyncio.run()函数关闭事件循环之前完成任务。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

码云笔记

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值