python协程函数 python协程用法

Python异步编程4:协程函数,协程对象,await关键字协程函数:async def 函数名 。3.5+
协程对象:执行协程函数()得到的协程对象 。
3.5之后的写法:
3.7之后的写法:更简便
await后面 跟 可等待的对象 。(协程对象,Future , Task对象 约等于IO等待)
await实例2:串行执行 。一个协程函数里面可以支持多个await,虽然会串行,但是如果有其他协程函数,任务列表也在执行,依然会切换 。只是案例中的main对应执行的others1和others2串行。await会等待对象的值得到之后才继续往下走 。
python协程(4):asyncio asyncio是官方提供的协程的类库,从python3.4开始支持该模块
asyncawiat是python3.5中引入的关键字,使用async关键字可以将一个函数定义为协程函数,使用awiat关键字可以在遇到IO的时候挂起当前协程(也就是任务) , 去执行其他协程 。
await + 可等待的对象(协程对象、Future对象、Task对象 - IO等待)
注意:在python3.4中是通过asyncio装饰器定义协程,在python3.8中已经移除了asyncio装饰器 。
事件循环,可以把他当做是一个while循环,这个while循环在周期性的运行并执行一些协程(任务) , 在特定条件下终止循环 。
loop = asyncio.get_event_loop():生成一个事件循环
loop.run_until_complete(任务):将任务放到事件循环
Tasks用于并发调度协程 , 通过asyncio.create_task(协程对象)的方式创建Task对象,这样可以让协程加入事件循环中等待被调度执行 。除了使用 asyncio.create_task() 函数以外,还可以用低层级的 loop.create_task() 或 ensure_future() 函数 。不建议手动实例化 Task 对象 。
本质上是将协程对象封装成task对象 , 并将协程立即加入事件循环,同时追踪协程的状态 。
注意:asyncio.create_task() 函数在 Python 3.7 中被加入 。在 Python 3.7 之前,可以改用 asyncio.ensure_future() 函数 。
下面结合asyncawiat、事件循环和Task看一个示例
示例一:
*注意:python 3.7以后增加了asyncio.run(协程对象),效果等同于loop = asyncio.get_event_loop(),loop.run_until_complete(协程对象) *
示例二:
注意:asyncio.wait 源码内部会对列表中的每个协程执行ensure_future从而封装为Task对象 , 所以在和wait配合使用时task_list的值为[func(),func()] 也是可以的 。
示例三:
python协程和异步IO——IO多路复用C10k是一个在1999年被提出来的技术挑战,如何在一颗1GHz CPU,2G内存,1gbps网络环境下,让单台服务器同时为1万个客户端提供FTP服务
阻塞式I/O(使用最多)、非阻塞式I/O、I/O复用、信号驱动式I/O(几乎不使用)、异步I/O(POSIX的aio_系列函数)
select、poll、epoll都是IO多路复用的机制 。I/O多路复用就是通过一种机制,一个进程可以监听多个描述符,一旦,某个描述符就绪(一般是读就绪或者写就绪),能够通知程序进行相应的读写操作 。但select、poll、epoll本质上都是同步I/O,因为他们都需要在读写时间就绪后负责进行读写,也就是说读写过程是阻塞的,而异步I/O无需自己负责进行读写,异步I/O的实现会负责把数据从内核拷贝到用户空间
(1)select
select函数监视的文件描述符分3类,分别是writefds、readfds、exceptfds 。调用select函数会阻塞,直到有描述符就绪(有数据可读、可写或者有except),或者超时函数返回 。当select函数返回后可以通过遍历fdset来找到就绪的描述符 。
select目前几乎在所有的平台上支持,其良好的跨平台支持也是它的一个优点 。select的一个缺点在于单个进程能够监视的文件描述符的数量存在最大限制,在Linux上一般为1024,可以通过修改宏定义甚至重新编译内核的方式提升这一限制,但是这样也会降低效率 。

推荐阅读