协程,英文名称为 Coroutine,常常被称为微线程,纤程,是一种多任务并发的操做手段
PYTHON 中的多任务处理,根据资源消耗状况能够选择多进程并发、多线程并发,同时也可
以在节省系统资源的状况下选择协程并发,协程因为是工做在一个线程中的执行单元,因此
系统资源消耗是最少的python
因为协程省去了多线程、多进程并发机制下的切换管理和状态数据管理等,因此操做效率较
高,PYTHON 不一样的版本中提供了很多关于协程的支持,咱们从最简单的多任务并发逐步深
入了解 PYTHON 中的协程多线程
协程既然是多任务并发,确定是参考了多线程的工做机制,咱们安装 gevent 模块完成最基
本的多任务操做协程
pip install gevent
并发
咱们回到最初的多任务并发,要求在程序中一边唱歌一边跳舞的功能实现异步
import time from greenlet import greenlet def sing(): # 定义唱歌的函数 while True: print("唱歌》》》") time.sleep(1) # 切换运行协程2 g2.switch() def dance(): while True: print("跳舞》》》》") time.sleep(1) # 切换运行协程1 g1.switch() if __name__ == "__main__": # 建立两个协程对象 g1 = greenlet(sing) g2 = greenlet(dance) # 切换到协程1工做 g1.switch() print("主进程执行...")
咱们经过事件操做模块gevent,让多个任务根据本身的运行状态进行自动切换async
import gevent import threading def sing(): # 定义唱歌函数 while True: print("唱歌>>>", threading.current_thread().getName()) # 事件休眠,让出执行时间片 gevent.sleep(1) def dance(): # 定义跳舞函数 while True: print("跳舞>>>", threading.current_thread().getName()) # 事件休眠,让出时间片 gevent.sleep(3) if __name__ == "__main__": # 常见跳舞、唱歌的协程 s = gevent.spawn(sing) d = gevent.spawn(dance) # 独占时间片运行 s.join() d.join()
执行代码运行程序,能够看到他们是工做在一个线程中的执行单元函数
Python 中为了有效的利用内存进行程序的运算操做,提供了一个生成器对象 yield
所谓生成器,就是在程序运行执行到该代码时才参与运算获得结果,常常被用做协程操做和
组合数据类型的推导生成
因为其执行即运算的特性,经过生成器操做也能够完成协程的处理oop
import time def sing(): while True: time.sleep(1) print("唱歌》》》") yield def dance(): while True: time.sleep(1) print("跳舞>>>") next(s) if __name__ == "__main__": s = sing() d = dance()
生成器对象主要的核心函数就是next(),经过next()方法才能执行运算获得运算的下一个结果值,因此这里有效的利用yield完成了一次协程的工做。可是毕竟yield错作协程的可读性较差。优化
PYTHON3.4 版本中添加了异步 io 操做模块 asyncio,对于协程的操做支持就变得比较友好
了,经过异步 io 操做,能够将多路 io 程序经过协程的方式提高操做效率spa
import asyncio # 添加一个注解,标注这个函数是一个协程函数 @asyncio.coroutine def show_info(name): for i in range(0, 10): print(name, "输出数据>>>") # 异步执行代码,模拟耗时2s yield from asyncio.sleep(2) if __name__ == "__main__": # 获取异步IO时间轮询对象 loop = asyncio.get_event_loop() # 编译执行 loop.run_until_complete(asyncio.gather(show_info("tom"), show_info("jerry"))) # 关闭时间 轮询 loop.close()
前面那个唱歌跳舞的异步IO协程改版线程
import asyncio @asyncio.coroutine def sing(): while True: print("唱歌》》》") yield from asyncio.sleep(2) @asyncio.coroutine def dance(): while True: print("跳舞》》》") yield from asyncio.sleep(2) if __name__ == "__main__": loop = asyncio.get_event_loop() loop.run_until_complete(asyncio.gather(sing(), dance())) loop.close()
PYTHON3.5 又增长了新的操做机制以提升对协程的支持
新增 async 替代了原来的@asyncio.corotine,新增 await 替代了原有的 yield from 步骤,简
化和优化了原有协程处理流程,这一部分异步操做,在之后的各个须要异步操做的方面都有
着很是普遍的应用。
import asyncio async def sing(): while True: print("唱歌》》》") # 异步操做 await asyncio.sleep(2) async def dance(): while True: print("不如跳舞》》》") await asyncio.sleep(1) if __name__ == "__main__": loop = asyncio.get_event_loop() loop.run_until_complete(asyncio.gather(sing(), dance())) loop.close()