一、协程
协程的概念
协程,又称微线程,纤程,也称为用户级线程,在不开辟线程的基础上完成多任务,也就是在单线程的情况下完成多任务,多个任务按照一定顺序交替执行 通俗理解只要在def里面只看到一个yield关键字表示就是协程。
协程是也是实现多任务的一种方式。
进程,线程和协程
- 进程是系统为cpu进行资源分配的单位;有进程号,用ps命令可以看到当前系统中的进程;进程切换需要的资源最大,效率很低;
- 线程是操作系统调度的单位,是真正的执行单元;线程切换需要的资源一般,效率一般(当然了在不考虑GIL的情况下);
- 协程切换任务资源很小,效率高。
多进程、多线程根据cpu核数不一样可能是并行的,但是协程是在一个线程中 所以是并发。
协程的优缺点
-
优点
a、最大的优势就是协程极高的执行效率。因为子程序切换不是线程切换,而是由程序自身控制,因此,没有线程切换的开销,和多线程比,线程数量越多,协程的性能优势就越明显。
b、不需要多线程的锁机制,因为只有一个线程,也不存在同时写变量冲突,在协程中控制共享资源不加锁,只需要判断状态就好了,所以执行效率比多线程高很多。
-
缺点
a、无法利用多核CPU,协程的本质是单个线程,它不能同时将多个CPU的多个核心使用上,失去了标准线程使用多CPU的能力。
b、进行阻塞操作(操作IO)会阻塞整个程序
二、同步与异步
1、同步与异步的概念
-
前言
python由于GIL(全局锁)的存在,不能发挥多核的优势,其性能一直饱受诟病。然而在IO密集型的网络编程里,异步处理比同步处理能提升成百上千倍的效率
IO密集型就是磁盘的读取数据和输出数据非常大的时候就是属于IO密集型
由于IO操作的运行时间远远大于cpu、内存运行时间,所以任务的大部分时间都是在等待IO操作完成,IO的特点是cpu消耗小,所以,IO任务越多,cpu效率越高,当然不是越多越好,有一个极限值。 -
同步
指完成事务的逻辑,先执行第一个事务,如果阻塞了,会一直等待,直到这个事务完成,再执行第二个事务,顺序执行
-
异步
是和同步相对的,异步是指在处理调用这个事务的之后,不会等待这个事务的处理结果,直接处理第二个事务去了,通过状态、通知、回调来通知调用者处理结果
2、同步与异步代码
-
同步
import time def run(index): print("lucky is a good man", index) time.sleep(2) print("lucky is a nice man", index) for i in range(1, 5): run(i) -
异步
说明:后面的课程中会使用到asyncio模块,现在的目的是使同学们理解异步思想
import time import asyncio async def run(i): print("lucky is a good man", i) # 模拟一个耗时IO await asyncio.sleep(2) print("lucky is a nice man", i) def test(): loop = asyncio.get_event_loop() tasks = [] t1 = time.time() for url in range(1, 5): coroutine = run(url) task = asyncio.ensure_future(coroutine) tasks.append(task) loop.run_until_complete(asyncio.wait(tasks)) t2 = time.time() print("总耗时:%.2f" % (t2 - t1)) if __name__ == "__main__": test() -
协程中yield的运用
说明:使用yield来实现一个简单的协程
import time def work1(): while True: print("----work1---") yield time.sleep(0.5) def work2(): while True: print("----work2---") yield time.sleep(0.5) def test(): w1 = work1() w2 = work2() while True: next(w1) next(w2) if __name__ == "__main__": test()
运行结果:
----work1—
----work2—
----work1—
----work2—
----work1—
----work2—
…
协程之间执行任务按照一定顺序交替执行。
三、asyncio模块
1、概述
-
asyncio模块
是python3.4版本引入的标准库,直接内置了对异步IO的操作
-
编程模式
是一个消息循环,我们从asyncio模块中直接获取一个EventLoop的引用,然后把需要执行的协程扔到EventLoop中执行,就实现了异步IO
-
说明
到目前为止实现协程的不仅仅只有asyncio,tornado和gevent都实现了类似功能
-
关键字的说明
关键字 说明 event_loop 消息循环,程序开启一个无限循环,把一些函数注册到事件循环上,当满足事件发生的时候,调用相应的协程函数 coroutine 协程对象,指一个使用async关键字定义的函数,它的调用不会立即执行函数,而是会返回一个协程对象。协程对象需要注册到事件循环,由事件循环调用 task 任务,一个协程对象就是一个原生可以挂起的函数,任务则是对协程进一步封装,其中包含了任务的各种状态 async/await python3.5用于定义协程的关键字,async定义一个协程,await用于挂起阻塞的异步调用接口
2、asyncio基本使用
-
定义一个协程
import asyncio import time # 通过async关键字定义了一个协程,协程是不能直接运行的,需要将协程放到消息循环中 async def run(x): print("waiting:%d"%x) await asyncio.sleep(x) print("结束run") #得到一个协程对象 coroutine = run(2) asyncio.run(coroutine)等同于
import asyncio import time # 通过async关键字定义了一个协程,协程是不能直接运行的,需要将协程放到消息循环中 async def run(x): print("waiting:%d"%x) await asyncio.sleep(x) print("结束run") #得到一个协程对象 coroutine = run(2) # 创建一个消息循环 loop = asyncio.get_event_loop() #将协程对象加入到消息循环 loop.run_until_complete(coroutine) -
创建一个任务
import asyncio import time async def run(x): print("waiting:%d"%x) await asyncio.sleep(x) print("结束run") coroutine = run(2) #创建任务 task = asyncio.ensure_future(coroutine) loop = asyncio.get_event_loop() # 将任务加入到消息循环 loop.run_until_complete(task) -
阻塞和await
async可以定义协程,使用await可以针对耗时操作进行挂起,就与生成器的yield一样,函数交出控制权。协程遇到await,消息循环会挂起该协程,执行别的协程,直到其他协程也会挂起或者执行完毕,在进行下一次执行
-
获取返回值
import time import asyncio async def run(url): print("开始向'%s'要数据……"%(url))<

最低0.47元/天 解锁文章
,asyncio模块的使用&spm=1001.2101.3001.5002&articleId=127493470&d=1&t=3&u=2f6804e7307f4b15a5593b12933cde16)
3万+

被折叠的 条评论
为什么被折叠?



