Python协程
进程(process):进程是操作系统资源分配的最小单位
进程有自己的虚拟地址空间,这个空间包括了各种资源,例如堆、栈,各种段,它们其实都是虚拟地址空间的一块区域。所以说进程是资源分配的最小单位。
线程(thread):线程是操作系统任务调度和执行的最小单位。
线程包含在进程之中,是进程中实际运作单位
协程(coroutine):
协程:线程中协作式调度的程序(函数)
协程(Coroutines)是一种比线程更加轻量级的存在,一个线程可以拥有多个协程。
线程和协程区别
①:线程是由操作系统调度和执行的。
协程是完全由程序代码所控制。
协程仅仅是一个特殊的函数,它可以在某个地方挂起,并且可以在挂起处继续执行,这样的好处是性能大幅度的提升,因为不会像线程切换那样消耗资源。
一个线程内的多个协程虽然可以切换(切换者是开发者),但是多个协程是串行执行的,只能在一个线程内运行,没法利用CPU多核能力
②:线程是操作系统抢占式调度的
协程是开发者自己决定什么时候让出,协程完全是用户态的行为,由程序员决定什么时候让出控制权,保存现场和切换恢复使用的资源也非常少,提高了处理效率
多进程和多线程除了创建的开销大之外还有一个难以根治的缺陷,就是处理进程之间或线程之间的协作问题,因为是依赖多进程和多线程的程序在不加锁的情况下通常是不可控的,而协程则可以完美地解决协作问题,由用户来决定协程之间的调度
Python协程
Python 中的异步函数通常称为“协程”。
Python协程只是一个使用async关键字的函数,或者用@asyncio.coroutine注解标注的函数(Python3.8之后该方式已过时,推荐使用async def的方式 ),如:
import asyncio async def ping_server(ip): pass @asyncio.coroutine def load_file(path): pass
这两种方式是等效的,并且在调用时返回的是协程对象的特殊函数。调用不会真正运行它们,而是返回一个协程对象,然后可以将其传递给事件循环以稍后执行。
判断一个函数是否是协程,使用asyncio提供asyncio.iscoroutinefunction(func_name)
判断从函数返回的对象是否是协程对象,使用asyncio.iscoroutine(obj)
async/await
Python在3.5版本中引入了关于协程的语法糖async和await
async用于将函数声明为协程,要实际调用此函数,使用await,await必须在另一个协程之内使用,不能在另一个协程之外使用。
协程(异步函数)的特点是能在函数执行过程中挂起,去执行其他异步函数,等挂起条件消失后,再回来执行。
await 用来声明当前程序挂起,去执行 await 后的异步函数,所以await后只能跟异步函数或有__await__属性的对象。
async def hello(): print("Hello world!") r = await asyncio.sleep(10) # 挂起hello函数,执行asyncio.sleep(10) print("Hello again!")
事件循环
事件循环是异步函数执行的核心
事件循环提供的功能:
①:注册、执行和取消执行异步函数
②:创建用于通信的客户端和服务器传输
③:创建子进程和传输以与另一个程序进行通信
④:将函数调用委托给线程池
事件循环执行协程(异步函数)示例:
async def coroutine_test(): return True if __name__ == '__main__': # 获取默认事件循环 loop = asyncio.new_event_loop() try: # 调度并运行异步函数,是阻塞的,在所有的异步函数执行完成之后才会返回 b = loop.run_until_complete(coroutine_test()) print(b) # True finally: # 循环运行完成后关闭循环 loop.close()
END.