Python协程:从yield/send到async/await
这个文章理好了脉落。
http://python.jobbole.com/86069/
我练 习了一番,感受好了很多。。。
Python由于众所周知的GIL的原因,导致其线程无法发挥多核的并行计算能力(当然,后来有了multiprocessing,可以实现多进程并行),显得比较鸡肋。既然在GIL之下,同一时刻只能有一个线程在运行,那么对于CPU密集的程序来说,线程之间的切换开销就成了拖累,而以I/O为瓶颈的程序正是协程所擅长的:
多任务并发(非并行),每个任务在合适的时候挂起(发起I/O)和恢复(I/O结束)
弄清楚了asyncio.coroutine和yield from之后,在Python3.5中引入的async和await就不难理解了:可以将他们理解成asyncio.coroutine/yield from的完美替身。当然,从Python设计的角度来说,async/await让协程表面上独立于生成器而存在,将细节都隐藏于asyncio模块之下,语法更清晰明了。
#!/usr/bin/env python # -*- coding: utf-8 -*- import asyncio import time import random ''' def old_fib(n): res = [0] * n index = 0 a = 0 b = 1 while index < n: res[index] = b a, b = b, a + b index += 1 return res print("-"*10 + "test old fib " + "-"*10) for fib_res in old_fib(20): print(fib_res) def fib(n): index = 0 a = 0 b = 1 while index < n: yield b a, b = b, a + b index += 1 print("-"*10 + "test yield fib " + "-"*10) for fib_res in fib(20): print(fib_res) def stupid_fib(n): index = 0 a = 0 b = 1 while index < n: sleep_cnt = yield b print("let me think {0} secs".format(sleep_cnt)) time.sleep(sleep_cnt) a, b = b, a + b index += 1 print("-"*10 + "test yield send " + "-"*10) N = 20 sfib = stupid_fib(N) fib_res = next(sfib) while True: print(fib_res) try: fib_res = sfib.send(random.uniform(0, 0.5)) except StopIteration: break def copy_fib(n): print("I am copy from fib") yield from fib(n) print("copy end") print("-"*10 + "test yield from " + "-"*10) for fib_res in copy_fib(20): print(fib_res) def copy_stupid_fib(n): print("I am copy from stupid fib") yield from stupid_fib(n) print("Copy end") print("-"*10 + "test yield from and send" + "-"*10) N = 20 csfib = copy_stupid_fib(N) fib_res = next(csfib) while True: print(fib_res) try: fib_res = csfib.send(random.uniform(0, 0.5)) except StopIteration: break @asyncio.coroutine def smart_fib(n): index = 0 a = 0 b = 1 while index < n: sleep_secs = random.uniform(0, 0.2) yield from asyncio.sleep(sleep_secs) print("Smart one think {} secs to get {}".format(sleep_secs, b)) a, b = b, a + b index += 1 @asyncio.coroutine def stupid_fib(n): index = 0 a = 0 b = 1 while index < n: sleep_secs = random.uniform(0, 0.4) yield from asyncio.sleep(sleep_secs) print("Stupid one think {} secs to get {}".format(sleep_secs, b)) a, b = b, a + b index += 1 loop = asyncio.get_event_loop() tasks = [ asyncio.async(smart_fib(10)), asyncio.async(stupid_fib(10)), ] loop.run_until_complete(async.wait(tasks)) print("All fib finished.") loop.close() ''' async def smart_fib(n): index = 0 a = 0 b = 1 while index < n: sleep_secs = random.uniform(0, 0.2) await asyncio.sleep(sleep_secs) print("Smart one think {} secs to get {}".format(sleep_secs, b)) a, b = b, a + b index += 1 async def stupid_fib(n): index = 0 a = 0 b = 1 while index < n: sleep_secs = random.uniform(0, 0.4) await asyncio.sleep(sleep_secs) print("Stupid one think {} secs to get {}".format(sleep_secs, b)) a, b = b, a + b index += 1 loop = asyncio.get_event_loop() tasks = [ asyncio.async(smart_fib(10)), asyncio.async(stupid_fib(10)), ] loop.run_until_complete(asyncio.wait(tasks)) print("All fib finished.") loop.close()
Python中的协程经历了很长的一段发展历程。其大概经历了如下三个阶段:
- 最初的生成器变形yield/send
- 引入@asyncio.coroutine和yield from
- 在最近的Python3.5版本中引入async/await关键字
Python协程:从yield/send到async/await的更多相关文章
- 理解Python协程:从yield/send到yield from再到async/await
Python中的协程大概经历了如下三个阶段:1. 最初的生成器变形yield/send2. 引入@asyncio.coroutine和yield from3. 在最近的Python3.5版本中引入as ...
- 终结python协程----从yield到actor模型的实现
把应用程序的代码分为多个代码块,正常情况代码自上而下顺序执行.如果代码块A运行过程中,能够切换执行代码块B,又能够从代码块B再切换回去继续执行代码块A,这就实现了协程 我们知道线程的调度(线程上下文切 ...
- 深入理解协程(四):async/await异步爬虫实战
本文目录: 同步方式爬取博客标题 async/await异步爬取博客标题 本片为深入理解协程系列文章的补充. 你将会在从本文中了解到:async/await如何运用的实际的爬虫中. 案例 从CSDN上 ...
- 深入理解协程(三):async/await实现异步协程
原创不易,转载请联系作者 深入理解协程分为三部分进行讲解: 协程的引入 yield from实现异步协程 async/await实现异步协程 本篇为深入理解协程系列文章的最后一篇. 从本篇你将了解到: ...
- 再议Python协程——从yield到asyncio
协程,英文名Coroutine.前面介绍Python的多线程,以及用多线程实现并发(参见这篇文章[浅析Python多线程]),今天介绍的协程也是常用的并发手段.本篇主要内容包含:协程的基本概念.协程库 ...
- Python协程笔记 - yield
生成器(yield)作为协程 yield实际上是生成器,在python 2.5中,为生成器增加了.send(value)方法.这样调用者可以使用send方法对生成器发送数据,发送的数据在生成器中会赋值 ...
- [转载] Python协程从零开始到放弃
Python协程从零开始到放弃 Web安全 作者:美丽联合安全MLSRC 2017-10-09 3,973 Author: lightless@Meili-inc Date: 2017100 ...
- python协程(yield、asyncio标准库、gevent第三方)、异步的实现
引言 同步:不同程序单元为了完成某个任务,在执行过程中需靠某种通信方式以协调一致,称这些程序单元是同步执行的. 例如购物系统中更新商品库存,需要用"行锁"作为通信信号,让不同的更新 ...
- 从yield 到yield from再到python协程
yield 关键字 def fib(): a, b = 0, 1 while 1: yield b a, b = b, a+b yield 是在:PEP 255 -- Simple Generator ...
随机推荐
- 微信小程序-关于post 过来服务器没有获取到数据问题
查看一下服务器接收的post 参数是以什么形式接收的 微信给出得demo 请求的方式是Json 参数传递的 所以如果服务器使用的from 表单形式接收数据需要更改微信小程序中的 header 将 he ...
- JavaScript自运行函数(function(){})()的理解
今天打开JQuery源文件(jquery-1.8.3), 看到JQuery的初始化过程是这样的 (function( window, undefined ) { // .... })( window ...
- Ubuntu 14.04.4官方默认更新源sources.list
Ubuntu 14.04.4官方默认更新源sources.list # deb cdrom:[Ubuntu LTS _Trusty Tahr_ - Release amd64 (20160217.1) ...
- Java的生日
你知道巴西的税务系统,亚马逊的Kindle阅读器以及韩国的第一大镁板制造厂有什么共同点吗?乍一看上去,这简直就是风马牛不相及,但是这些系统同世界上其它100亿个设备共享一个元素,那就是Java. 19 ...
- log4j日志工具
一.关于日志 1.日志定义: 项目在运行阶段产生的信息 2.日志级别 最常见的日志级别有4个: error :错误日志 warn:警告日志 info:流程日志 debug:调试日志 优先级从高到低 ...
- [NHibernate]存储过程的使用(三)
目录 写在前面 文档与系列文章 查询 总结 写在前面 前面的文章介绍了在nhibernate中使用存储过程进行增删改的操作,当然查询也是可以的,在nhibernate中也可以执行任意的存储过程.本篇文 ...
- 惊艳!9个不可思议的 HTML5 Canvas 应用试验
HTML5 <canvas> 元素给网页中的视觉展示带来了革命性的变化.Canvas 能够实现各种让人惊叹的视觉效果和高效的动画,在这以前是需要 Flash 支持或者 JavaScript ...
- CentOS 安装tomcat 7
安装环境:CentOS-6.3 安装方式:源码安装 软件:apache-tomcat-7.0.29.tar.gz 下载地址:http://tomcat.apache.org/download-70.c ...
- SpringMVC Controller介绍
SpringMVC Controller 介绍 一.简介 在SpringMVC 中,控制器Controller 负责处理由DispatcherServlet 分发的请求,它把用户请求的数据经过业务处理 ...
- python 环境配置
每个项目都应该有自己的虚拟环境,如何方便的操作呢? 1. 安装 virtualenv 2. 安装 virtualenvwrapper 3. 创建目录用来存放虚拟环境 mkdir $HOME/.virt ...