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 ...
随机推荐
- 通过form上传文件(php)
前段代码 <html> <head> <meta http-equiv="Content-Type" content="text/html; ...
- C/C++中的声明与定义
含义 声明(Declaration), 用于告诉编译器被声明的函数/变量的存在, 及它们的类型/调用格式信息, 以检查是否被正确调用. 声明不分配内存空间. 定义(Definition), 用于告诉编 ...
- 教你一招:Excel中使用vlookup函数查询序列所对应的值
以一个简单的例子做示范,列数相对较少,看起来也比较清楚:在奥运会或其他比赛上我们可以看到各个国家的奖牌数的变化:那么我们如何查询国家对应的总奖牌数. 我们用到的函数是vlookup,它是一个纵向查询函 ...
- cxf设置代理访问webservice接口
由于业务上的需要,需要访问第三方提供的webservice接口,但由于公司做了对外访问的限制,不设置代理是不能外网的,如果使用http设置代理访问外网还是比较容易的,但使用cxf有点不知道从哪里入手. ...
- Html特殊字符表
原始字符 entity 原始字符 entity " " & & ' ' < < > > ¡ ¡ ¢ ¢ £ £ ¤ ¤ ¥ ¥ ¦ ...
- python学习笔记-(十五)RabbitMQ队列
rabbitMQ是消息队列:想想之前的我们学过队列queue:threading queue(线程queue,多个线程之间进行数据交互).进程queue(父进程与子进程进行交互或者同属于同一父进程下的 ...
- DEDECMS标签调用汇总啊
非常有用的标签调用的方法 关键描述调用标签: <meta name="keywords" content="{dede:field name='keywords'/ ...
- PHP5.6启动失败
PHP编译安装完毕,启动失败,提示 1 [23-Jun-2014 12:27:02] ERROR: failed to open configuration file '/usr/local/php/ ...
- 关于Java集合的小抄
在尽可能短的篇幅里,将所有List.Map.Set.Queue的特征与实现方式捋一遍.适合所有"精通Java"其实还不那么自信的人阅读. List ArrayList 以数组实现. ...
- Hbase过滤器Filter的使用心得(爬坑经验)
Hbase 的过滤器是个好东西.. 给这种非关系型数据库本来不能复杂查询的情况得到了很好的扩展..提供了很多的帮助.. 但是Filter的种类何其之多..让人眼花缭乱.. 譬如..分页类型的PageF ...