Python asyncio模块:异步I/O 初探协程

本文介绍了Python的asyncio模块,重点讲解如何创建和运行协程,以及并发执行多个协程的方法,包括asyncio.run(), asyncio.create_task(), asyncio.wait()和asyncio.gather()。通过实例展示了它们在并发执行中的行为和结果,帮助理解Python异步编程的核心概念。" 114830583,7352261,Verilog generate语句详解:for、if和case,"['硬件描述语言', 'Verilog语法', '数字电路设计']
摘要由CSDN通过智能技术生成

Python中的asyncio是一个使用事件循环驱动的协程实现高并发的标准库。下面简单记录asyncio的学习心得。

本文知识点速览:
创建一个协程
async def 句法定义一个协程函数coro,调用协程函数返回一个协程对象。
即coro -->协程函数;coro() -->协程对象。

运行一个协程
1.asyncio.run() :只应在最外层调用主协程main()时使用。
2.在一个外层协程函数中使用await语句运行协程。
3.使用asyncio.create_task()asyncio.ensure_future()将协程包装在一个Task对象中,python 会自动schedule该协程的执行。

多协程并发
awaitable:协程、Task、Future

1.asyncio.gather():接受一堆awaitable作为可变参数(传入协程会自动包装成Task),并发执行所有awaitable。返回的是一个Future。
执行该Future对象:
可以传入loop.run_until_completed()执行;
也可以在外层协程函数中被await执行;
也可以包装在一个外层main()协程中通过asyncio.run()执行。

获取结果:
Future对象执行完毕后返回一个二元素tuple,从中可提取到一堆Task对象,调用task.result()获取返回值,返回值的顺序与传入的awaitable顺序相关。

2.asyncio.wait() :接受一个包含awaitable的列表(其中的协程会自动包装为Task),并发执行所有awaitable。返回的是一个协程。
协程的运行不用多说了吧。。。

获取结果:
该协程对象直接返回一个包含了每个awaitable返回值的列表。返回值的顺序与传入的awaitable顺序相关。

3.asyncio.as_completed():接受一个包含awaitable的列表,返回的是一个生成器,产出Future。
Each Future object returned represents the earliest result from the set of the remaining awaitables.
参照文档,运行和获取结果的标准用法如下:

async def main():
    results = []
    awaitable_list = [awaitable_work(x, y) for x, y in zip((1, 2, 3), 'ABC')]
    for future in asyncio.as_completed(awaitable_list):
        result = await future
        results.append(result)
    return results

print('Results:', asyncio.run(main()))

##########################################################################################
正文开始:

定义一个协程函数
asyncio文档中特别强调要区分协程函数和协程对象的区别:
a coroutine function: an async def function;
a coroutine object: an object returned by calling a coroutine function.
通过async def 句法定义一个协程函数,调用该函数获得协程对象。
下文中所有“协程”仅指协程对象。

async def awaitable_work(time, name):
    print('Enter {}...will sleep {}s'.format(name, time))
    await asyncio.sleep(time)
    print('Done {}...for {}s.'.format(name, time))
    
asyncio.iscoroutine(awaitable_work(1, 'A') # True
asyncio.iscoroutinefunction(awaitable_work)  # True

协程无法直接执行。
执行一个协程有三种基本方法:
第一种方法
asyncio.run(coro, *, debug=False),仅接收协程对象作为参数,它实际上也是通过event loop来执行。调用该函数会创建一个新的event loop并在执行完毕后关闭该loop。如果当前线程已经有一个运行中的event loop,该函数无法执行。根据文档建议,这种方法仅应用于在最外层代码中启动主协程。

第二种方法
在一个外层协程函数的定义体中,通过await语句执行协程。
(ps:await语句也只能在协程的函数体中使用)。await语句是生成器中yield from 的代替品。
在外层协程中执行x = await y,如果y是一个协程,相当于y获得执行权。直到y全部执行完毕,外层协程取回执行权,将y的返回值赋给x。

async def outter_coro():
    await awaitable_work(2, 'B'))
    await awaitable_work(4, 'C'))
asyncio.run(outter_coro())

这里await的两个协程执行是线性的,共计执行6s,非并发

第三种方法
使用asyncio.create_task(coro),根据文档的描述:The asyncio.create_task() function to run coroutines concurrently as asyncio Tasks.
包装成为task对象之后,coro的执行是并发的。
先来看一下asyncio.create_task的源码,很简单

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值