Python,作为一门流行的编程语言,不仅具备清晰简洁的语法和强大的生态系统,还在异步编程领域拥有丰富而灵活的工具,其中包括协程、异步IO以及asyncio库。本文将深入探讨这些概念的本质,解释它们的原理,并通过实际示例演示如何应用它们,帮助我们更好地理解和利用Python的异步编程能力。
Python协程:
异步IO:
asyncio:
协程是一种轻量级的线程,它允许函数在执行过程中暂停并恢复。与常规函数不同,协程具有多个入口点,可以在函数内部的任何位置暂停和继续执行。Python的协程通过async和await关键字来定义和管理。
在Python中,协程的基本概念如下:
下面是一个简单的协程示例,演示了如何使用协程来实现异步任务:
import asyncio
async def hello(arg):
print("Hello : ",arg)
if arg == "SRE 1":
await asyncio.sleep(2)
else:
await asyncio.sleep(1)
print("World : ",arg)
print("bingo!!")
async def main():
await asyncio.gather(hello("SRE 1"), hello("SRE 2"), hello("SRE 3"))
asyncio.run(main())
运行可以看到日志
Hello : SRE 1
Hello : SRE 2
Hello : SRE 3
World : SRE 2
bingo!!
World : SRE 3
bingo!!
World : SRE 1
bingo!!
在这个示例中,hello函数是一个协程,通过await asyncio.sleep(1)来模拟一个耗时的操作。main函数使用await asyncio.gather()来同时运行多个协程。
异步IO是一种编程模型,用于处理非阻塞的IO操作。它使程序能够在执行IO操作时继续执行其他任务,而不必等待IO操作完成。
异步IO的核心概念包括:
以下示例演示了如何使用异步IO进行文件读取操作:
import asyncio
# 定义一个异步函数,模拟一个非阻塞的IO操作
async def non_blocking_io_operation(arg):
print("开始非阻塞IO操作")
if arg == "task1":
await asyncio.sleep(2) # 模拟IO操作,这里使用await来模拟异步操作
else:
await asyncio.sleep(5)
print(f"完成调用:{arg} 的非阻塞IO操作")
# 创建一个事件循环
async def main():
# 将非阻塞IO操作放入事件循环中
task1 = asyncio.create_task(non_blocking_io_operation("task1"))
task2 = asyncio.create_task(non_blocking_io_operation("task2"))
# 等待所有任务完成
await task1
print("完成task1 IO执行!")
await task2
print("完成task2 IO执行!")
# 启动事件循环
if __name__ == "__main__":
asyncio.run(main())
执行输出日志
开始非阻塞IO操作
开始非阻塞IO操作
完成调用:task1 的非阻塞IO操作
完成task1 IO执行!
完成调用:task2 的非阻塞IO操作
完成task2 IO执行!复制
asyncio 是异步 I/O 的缩写。它是一个 Python 库,允许我们使用异步编程模型运行代码。这让我们可以同时处理多个 I/O 操作,同时仍然允许我们的应用程序保持响应能力。
Python 3.4 引入了 asyncio 库,Python 3.5 生成了 async 和await 关键字以方便地使用它。这些新增功能允许所谓的异步编程。
asyncio库的基本概念包括:
以下示例展示了如何使用asyncio库来并发执行多个协程任务:
import asyncio
async def task1():
print("into task1 ....")
await asyncio.sleep(2)
print("Task 1 completed")
async def task2():
print("into task2 ...")
await asyncio.sleep(1)
print("Task 2 completed")
async def main():
task1_handle = asyncio.create_task(task1())
task2_handle = asyncio.create_task(task2())
await task1_handle
await task2_handle
asyncio.run(main())
在这个示例中,我们使用asyncio.create_task()创建了两个协程任务,并且可以并发执行它们。await关键字用于等待任务完成。
事件循环是 asyncio 应用程序的核心,负责处理所有正在运行的任务。事件循环支持多任务处理。当一个函数被挂起时,控制权返回到循环,然后循环找到另一个函数来启动或恢复。
loop = asyncio.get_event_loop()
loop.run_until_complete(my_coroutine())
loop.close()
示例
import asyncio
import time
async def cor1():
print("cor 1 started")
for i in range(5):
await asyncio.sleep(1.5)
print("cor1", i)
async def cor2():
print("cor 2 started")
for i in range(8):
await asyncio.sleep(1)
print("cor2", i)
loop = asyncio.get_event_loop()
cors = asyncio.wait([cor1(), cor2()])
loop.run_until_complete(cors)复制
运行可以得到输出
cor 2 started
cor 1 started
cor2 0
cor1 0
cor2 1
cor1 1
cor2 2
cor2 3
cor1 2
cor2 4
cor1 3
cor2 5
cor2 6
cor1 4
cor2 7
任务用于同时调度协程。我们使用函数 create_task() 创建一个任务。使用此函数将协程包装到任务中。
示例
import asyncio
import time
async def main():
# 使用 asyncio.create_task() 方法创建任务
task1 = asyncio.create_task(foo('task 1 run'))
task2 = asyncio.create_task(foo('task 2 run'))
print(f"started at {time.strftime('%X')}")
# 等待所有任务执行完成
await task1
await task2
print(f"finished at {time.strftime('%X')}")
async def foo(text):
print(text)
await asyncio.sleep(1)
asyncio.run(main())
得到输出
started at 17:35:47
task 1 run
task 2 run
finished at 17:35:48
为了执行并发执行,我们使用函数 Gather 如下。可等待的 asyncio.gather(*aws, return_exceptions=False)
该函数采用任意数量的可等待项(协程、任务等)作为参数。
示例
import asyncio
# 定义一个异步函数,用于打印文本并在每次打印后等待一段时间
async def printing(task, text):
while True:
print(task, text)
try:
await asyncio.sleep(0.50) # 等待0.50秒,模拟异步操作
except asyncio.CancelledError:
break # 如果收到取消请求,跳出循环结束任务
async def main():
try:
# 使用 asyncio.wait_for 设置一个超时时间为 3 秒,同时并发运行三个打印任务
await asyncio.wait_for(
asyncio.gather(
printing("A", "task 1"),
printing("B", "task 2"),
printing("C", "task 3")
), 3 # 超时时间设置为 3 秒
)
except asyncio.TimeoutError:
print("Time over") # 如果超时,打印 "Time over" 提示
asyncio.run(main())
得到输出
A task 1
B task 2
C task 3
A task 1
B task 2
C task 3
A task 1
B task 2
C task 3
A task 1
B task 2
C task 3
A task 1
B task 2
C task 3
A task 1
B task 2
C task 3
Time over
_GatheringFuture exception was never retrieved
future: <_GatheringFuture finished exception=CancelledError()>
concurrent.futures._base.CancelledError
异步编程提高了应用程序性能和响应能力。Python 提供了支持异步编程的不同库。Asyncio允许我们使用 async/await 语法编写并发代码。Asyncio 由协程、任务、流、子进程、异常等高级 API 和事件循环、Futures、传输和协议等低级 API 组成。
可以查看原文:
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。