这个文章理好了脉落。

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中的协程经历了很长的一段发展历程。其大概经历了如下三个阶段:

  1. 最初的生成器变形yield/send
  2. 引入@asyncio.coroutine和yield from
  3. 在最近的Python3.5版本中引入async/await关键字

Python协程:从yield/send到async/await的更多相关文章

  1. 理解Python协程:从yield/send到yield from再到async/await

    Python中的协程大概经历了如下三个阶段:1. 最初的生成器变形yield/send2. 引入@asyncio.coroutine和yield from3. 在最近的Python3.5版本中引入as ...

  2. 终结python协程----从yield到actor模型的实现

    把应用程序的代码分为多个代码块,正常情况代码自上而下顺序执行.如果代码块A运行过程中,能够切换执行代码块B,又能够从代码块B再切换回去继续执行代码块A,这就实现了协程 我们知道线程的调度(线程上下文切 ...

  3. 深入理解协程(四):async/await异步爬虫实战

    本文目录: 同步方式爬取博客标题 async/await异步爬取博客标题 本片为深入理解协程系列文章的补充. 你将会在从本文中了解到:async/await如何运用的实际的爬虫中. 案例 从CSDN上 ...

  4. 深入理解协程(三):async/await实现异步协程

    原创不易,转载请联系作者 深入理解协程分为三部分进行讲解: 协程的引入 yield from实现异步协程 async/await实现异步协程 本篇为深入理解协程系列文章的最后一篇. 从本篇你将了解到: ...

  5. 再议Python协程——从yield到asyncio

    协程,英文名Coroutine.前面介绍Python的多线程,以及用多线程实现并发(参见这篇文章[浅析Python多线程]),今天介绍的协程也是常用的并发手段.本篇主要内容包含:协程的基本概念.协程库 ...

  6. Python协程笔记 - yield

    生成器(yield)作为协程 yield实际上是生成器,在python 2.5中,为生成器增加了.send(value)方法.这样调用者可以使用send方法对生成器发送数据,发送的数据在生成器中会赋值 ...

  7. [转载] Python协程从零开始到放弃

    Python协程从零开始到放弃 Web安全 作者:美丽联合安全MLSRC   2017-10-09  3,973   Author: lightless@Meili-inc Date: 2017100 ...

  8. python协程(yield、asyncio标准库、gevent第三方)、异步的实现

    引言 同步:不同程序单元为了完成某个任务,在执行过程中需靠某种通信方式以协调一致,称这些程序单元是同步执行的. 例如购物系统中更新商品库存,需要用"行锁"作为通信信号,让不同的更新 ...

  9. 从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 ...

随机推荐

  1. localStorage与sessionStorage 的区别

    通过一枚页面计数器来区别localStorage与sessionStorage. 通过一个计数变量pageconut,每刷新页面,增加的是localStorage的数量,而sessionStorage ...

  2. JavaScript零基础学习系列四

    案例分享 对象 具体的东西,在以js的眼光看所有的标签都是标签对象,对象是属性的无序集合. 创建对象有两种方式: 直接量: 构造器:所谓的构造器,其实就是函数,只不过这个函数有些特殊,因为它是用于创建 ...

  3. Android只能动态注册的广播Action

    只能动态注册的广播(部分): android.intent.action.SCREEN_ON android.intent.action.SCREEN_OFF android.intent.actio ...

  4. jQuery控制表头

    <!doctype html><html lang="en"><head> <meta charset="UTF-8" ...

  5. “is null”与“=”的使用

    普通的值可以进行"="操作,例如条件中一般都会这样出现:sUserName='张三',如果sUserName的值为null,要想找出所 有名字为null的记录时,不能这样用:sUs ...

  6. bc#54 div2

    用小号做的div2 A:竟然看错了排序顺序...白白WA了两发 注意读入一整行(包括空格):getline(cin,st) [gets也是资瓷的 #include<iostream> us ...

  7. [noip科普]关于LIS和一类可以用树状数组优化的DP

    预备知识 DP(Dynamic Programming):一种以无后效性的状态转移为基础的算法,我们可以将其不严谨地先理解为递推.例如斐波那契数列的递推求法可以不严谨地认为是DP.当然DP的状态也可以 ...

  8. Bzoj2154 Crash的数字表格 乘法逆元+莫比乌斯反演(TLE)

    题意:求sigma{lcm(i,j)},1<=i<=n,1<=j<=m 不妨令n<=m 首先把lcm(i,j)转成i*j/gcd(i,j) 正解不会...总之最后化出来的 ...

  9. 了解了下 Google 最新的 Fuchsia OS

    就是看到篇报道,有点好奇,就去FQ挖了点东西回来. 我似乎已开始就抓到了重点,没错,就是 LK . LK 是 Travis Geiselbrecht 写的一个针对 ARM 的嵌入式操作系统,开源的.点 ...

  10. 使用Spring进行统一日志管理 + 统一异常管理

    http://blog.csdn.net/king87130/article/details/8011843原文地址 统一日志异常实现类: 1 package com.pilelot.web.util ...