异步IO:Python中的协程
来源:互联网 发布:辐射3低配置优化补丁 编辑:程序博客网 时间:2024/05/21 14:01
我们在实际的问题中会遇到一些堵塞线程的场景,比如UI程序进行耗时的计算阻塞主线程;进行IO操作,比如读写文档或者网络传输时会阻塞线程等等,之前我采用的是使用多进程+多线程的处理方式,但这种方式相比于协程来说都比较慢,特别是在Windows操作系统下启动一个进程的开销是巨大的,因此掌握Python中的协程对于处理一些高并发需求来说是非常重要的,看完了廖雪峰的官方网站–异步IO后我总结了一下我对于协程的理解以及yield, yield from asyc ,await等语法的理解
Python的协程基础在于生成器,生成器可以在我们需要的时候执行运算,得出执行结果,构造一个生成器有两种方法。
一是使用():(x * x for x in range(10)) 列表使用中括号[],生成器使用小括号
二是在函数中使用yield,此时该函数就不是一个函数,而是一个生成器对象
我们主要使用第二种方法来定义一个生成器,接下来我介绍对于yield, yield from 以及python3.5的新语法async/await
yield
我以一个简单的例子来介绍yield语法:
def test(times): return_info = '' n = 0 while n < times: n += 1 recv = yield n print("生成器收到数据%s" % recv) print("生成器结束")generator = test(5)
上述代码最主要的部分在于 recv = yield n,在等号左边和后边将代码块分成了两部分。
当我们启动生成器之后,代码会运行到yield n 后中断,并将yield 之后的表达式的值返回给generator.send(“要发送的数据”),也就是return_info = generator.send(“要发送的数据”) 此时return_info == n。
当我们再次通过send(“要发送的数据”)启动生成器时,会从上次中断的地方开始重新启动,也就是从等号的左边开始执行,将send(“要发送的数据”)中的数据赋值给recv,然后继续执行代码直到下一次的yield n后中断。
我们需要注意的一点是,当我们生成一个生成器generator之后,我们使用generator.send(None)来启动生成器,此时generator.send(None)相当于next(generator),第一次运行generator时必须send(None),因为根据yield语法,第一次执行生成器会在yield n 处中断,此时recv没有接受值,所以只能为None,这一部分在后面了解了yield的运行机制后就会明白,下面简单画一个图
2、yield from
yield from可以很方便地让我们调用另一个generator,yield from 建立了用户端到内层generator之间的”通信”,也可以方便我们在内层generator中处理异常。我们可以看以下代码:
def inner(): coef = 1 total = 0 while True: input_val = yield total if input_val is 2: print('break') break total = total + coef * input_val print("inner end")def outer2(): print("Before inner(), I do this.") a = yield from inner() print(a) print("After inner(), I do that.")c = outer2()a = c.send(None)print(a)print("first send end")b = c.send(2)print(b)
输出结果为
Before inner(), I do this.0first send endbreakinner endNoneAfter inner(), I do that.
当我们启动生成器时,代码会执行到yield from inner(),然后进入内层的generator,执行到yield total,此次代码执行结束,进入中断。
当我们第二次启动生成器时,c.send(2)会将2直接传递给内层的input_val,然后执行内层的yield,打印出’break’,内层的yield结束,打印出’inner end’,由于此时是中断,没有yield,即没有返回值,那么yield from inner()的返回值为None,打印出a为None,最后打印结束语句,退出程序。
此时我们可以看出,yield from会将send的值传递到最里层,再次启动生成器也是从最里层的yield开始启动,然后当内层的yield结束后执行外层的yield直到程序结束。我们可以画一个示例图帮助理解
3、async/await
async和await是python3.5之后的新语法,可以用来替换@asyncio.coroutine和await。
async可以将一个generator标记为coroutine类型,然后将其放入event_loop中执行,当我们在event_loop中放入多个coroutine的generator后,我们启动事件循环,此时遇到await,该generator就会中断,继续执行下一个generator,直到所有的generator的await执行完成后,event_loop再开始下一次消息循环,此时会再次启动event_loop中的生成器。
举一个形象地例子就是你在快餐店排队,每一个人在收银台付款后(await money),到取餐处等待,直到每个人都付款之后,开始打包外卖,谁的先做好就可以拿走,而不是根据付款的顺序来取餐。
关于异步IO在服务器编程方面用到的地方很多,了解了基本的特性后,还需要大量的实际编程经验才能真正掌握python中协程的概念,继续去填坑了0.0。。。
- 异步IO:Python中的协程
- 异步IO:Python中的协程
- Python中的异步IO和协程
- python异步IO和协程
- Python学习:异步IO:协程和asyncio
- Python并发编程之协程/异步IO
- Python中的协程和异步编程
- Python下异步IO和协程简介
- python 异步IO
- python 异步IO
- 【asyncio】python异步IO
- 服务端中的异步IO
- Python poll实现异步IO
- python爬虫之异步IO
- oracle数据库中的异步IO
- 关于IO中的同步异步
- oracle数据库中的异步IO
- 服务端异步IO配合协程浅析
- Tomcat文件夹下conf文件夹中的context.xml文件存在的目的是什么
- MaxCompute2.0性能评测:更强大、更高效之上的更快速
- 关于发送jsonp请求的问题
- IE可以上网其他浏览器上不了
- windows串口读取C(3)
- 异步IO:Python中的协程
- MVP(Retrofit+RXJava)实现网络请求
- Linux驱动中,probe函数何时被调用
- 新的思想控制的假肢恢复了触觉的感觉
- 虚幻4内置后期效果
- Redis 有序集合(sorted set)
- LEADTOOLS V19 版本更新,文档和医疗成像技术速度和精度得到优化
- JSON基础
- Java实现AOP的两种方式