在前面几个博客中我们一一对应解决了消费者消费的速度跟不上生产者,浪费我们大量的时间去等待的问题,在这里,针对业务逻辑比较耗时间的问题,我们还有除了多进程之外更优的解决方式,那就是协程和异步协程。在引入这个概念之前我们先看   看这个图:                                                                                                                                   

从这个图片我们可以看出来,假如来了9个任务,即使我们开了多进程,在业务的执行过程中我们依旧是同步操作,所以执行完这一波任务我们一共需要9s,虽然比单进程快了3倍,但是在机器条件可以(肯定可以)的情况下,我们如何更加合理的利用给我们的资源呢?于是异步协程的优势就来了:

根据这张图我们可以看出来,在任务1执行完业务逻辑1的时候,任务2就可以开始执行,这样当任务2执行完业务逻辑1的时候,任务3就开始执行了,这样我们3个进程,总共耗时只需要5s,比上面同步的方式快了足足4s,省去了等待的时间,让模块之间衔接和调用更加充分。

在python中,我们先介绍一下2.0的协程:gevent的使用,在python3.4之后添加了syncoio的使用,这篇博客我们就专门针对业务逻辑部分进行深度的优化:

gevent是第三方库,通过greenlet实现协程,其基本思想是:

当一个greenlet遇到IO操作时,比如访问网络,就自动切换到其他的greenlet,等到IO操作完成,再在适当的时候切换回来继续执行。由于IO操作非常耗时,经常使程序处于等待状态,有了gevent为我们自动切换协程,就保证总有greenlet在运行,而不是等待IO(引用)。

比如下面代码:

from gevent import monkey
monkey.patch_all() import gevent
import time # TODO 此处是业务逻辑操作
def logicDel(data):
time.sleep(2)
print('im running',data) if __name__ == '__main__':
# 在这里我们声明几个任务,把任务放到一个list中去做分配调度
tasks=[gevent.spawn(logicDel,data) for data in range(9)]
gevent.joinall(tasks)

我们可以看到我们在一个tasks里面9个任务,每个任务执行都要sleep2秒,如果是阻塞式运行就需要18s,但是我们加入了协程,所有的任务完成只需要2s,其中原理和上图(异步加载图)一样,这里就不赘述了。

然而有时候我们代码业务逻辑中一个业务执行不只有一个任务,其中每个任务之间还有调度依赖的关系,这时候我们的gevent就显得有点力不从心了,这里就引进了python3.4之后的一个自带的包asyncio——异步协程。

asyncio的编程模型就是一个消息循环。我们从asyncio模块中直接获取一个EventLoop的引用,然后把需要执行的协程扔到EventLoop中执行,就实现了异步IO。用asyncio实现Hello world代码如下:

import threading
import asyncio @asyncio.coroutine
def hello():
print('Hello world11111111 (%s)' % threading.currentThread())
yield from asyncio.sleep(1)
print('Hello again22222222 (%s)' % threading.currentThread()) loop = asyncio.get_event_loop()
tasks = [hello(), hello()]
loop.run_until_complete(asyncio.wait(tasks))
loop.close()

其中每个tasks都是非阻塞式的,当然这个还是没有解决一个业务有多个任务且每个任务之间存在依赖关系应当怎么解决的问题,因为我们还没有引用async await:

import asyncio
import time # Borrowed from http://curio.readthedocs.org/en/latest/tutorial.html.
# @asyncio.coroutine
async def myslep(n):
print(n)
time.sleep(10)
asyncio.sleep(5) async def countdown(number, n):
while n > 0:
print('T-minus', n, '({})'.format(number))
# await myslep(n)
tasks2=[]
await asyncio.ensure_future(myslep(n))
# time.sleep(2)
n -= 1 loop = asyncio.get_event_loop()
tasks = [
asyncio.ensure_future(countdown("A", 2)),
asyncio.ensure_future(countdown("B", 3)),
asyncio.ensure_future(countdown("C", 3)),
] loop.run_until_complete(asyncio.wait(tasks)) loop.close()

python协程与异步协程的更多相关文章

  1. 小爬爬4.协程基本用法&&多任务异步协程爬虫示例(大数据量)

    1.测试学习 (2)单线程: from time import sleep import time def request(url): print('正在请求:',url) sleep() print ...

  2. 进击的Python【第十章】:Python的socket高级应用(多进程,协程与异步)

    Python的socket高级应用(多进程,协程与异步)

  3. Python【第十篇】协程、异步IO

    大纲 Gevent协程 阻塞IO和非阻塞IO.同步IO和异步IO的区别 事件驱动.IO多路复用(select/poll/epoll) 1.协程 1.1协程的概念 协程,又称微线程,纤程.英文名Coro ...

  4. Day10 - Python协程、异步IO、redis缓存、rabbitMQ队列

    Python之路,Day9 - 异步IO\数据库\队列\缓存   本节内容 Gevent协程 Select\Poll\Epoll异步IO与事件驱动 Python连接Mysql数据库操作 RabbitM ...

  5. 带你简单了解python协程和异步

    带你简单了解python的协程和异步 前言 对于学习异步的出发点,是写爬虫.从简单爬虫到学会了使用多线程爬虫之后,在翻看别人的博客文章时偶尔会看到异步这一说法.而对于异步的了解实在困扰了我好久好久,看 ...

  6. Python实现基于协程的异步爬虫

    一.课程介绍 1. 课程来源 本课程核心部分来自<500 lines or less>项目,作者是来自 MongoDB 的工程师 A. Jesse Jiryu Davis 与 Python ...

  7. Python学习——多线程,异步IO,生成器,协程

    Python的语法是简洁的,也是难理解的. 比如yield关键字: def fun(): for i in range(5): print('test') x = yield i print('goo ...

  8. python——asyncio模块实现协程、异步编程

    我们都知道,现在的服务器开发对于IO调度的优先级控制权已经不再依靠系统,都希望采用协程的方式实现高效的并发任务,如js.lua等在异步协程方面都做的很强大. Python在3.4版本也加入了协程的概念 ...

  9. 消息/事件, 同步/异步/协程, 并发/并行 协程与状态机 ——从python asyncio引发的集中学习

    我比较笨,只看用await asyncio.sleep(x)实现的例子,看再多,也还是不会. 已经在unity3d里用过coroutine了,也知道是“你执行一下,主动让出权限:我执行一下,主动让出权 ...

随机推荐

  1. Angular09 数据绑定、响应式编程、管道

    1 数据绑定的分类 1.1 单向数据绑定 1.1.1 属性绑定 -> 数据从组件控制类到组件模板 DOM属性绑定 HTML属性绑定 1.1.2 事件绑定 -> 数据从组件模板到组件控制类 ...

  2. PCLVisualizer可视化类(2)

    博客转载自:http://www.pclcn.org/study/shownews.php?lang=cn&id=163 可视化点云颜色特征 所示,点赋予不同的颜色表征其对应的z轴值不同.PC ...

  3. 15、使用ggtree实现进化树的可视化和注释(转载)

    本文作者:余光创,目前就读于香港大学公共卫生系,开发过多个R/Bioconductor包,包括ChIPseeker, clusterProfiler, DOSE,ggtree,GOSemSim和Rea ...

  4. 滴水穿石 C#中多线程 委托的使用

    什么是多线程?我们在建立以个C#项目时,往往会在Form1上添加控件,然后写代码,初 学者都是在重复这个过程,其实这个过程是单线程的,可以理解为只有“main”主线程,有 的时候往往需要同时测量多个东 ...

  5. Note: Differentially Private Access Patterns for Searchable Symmetric Encryption

    The Core Issues and Ideas of This Paper Problem Baseline Searchable Symmetric Encryption (SSE) could ...

  6. scrapy-redis源码解读之发送POST请求

    1 引言 这段时间在研究美团爬虫,用的是scrapy-redis分布式爬虫框架,奈何scrapy-redis与scrapy框架不同,默认只发送GET请求,换句话说,不能直接发送POST请求,而美团的数 ...

  7. SAS笔记(8) 利用数组重构SAS数据集

    在实际应用中,我们经常会把宽数据(一个患者一条观测)转化为长数据(一个患者多条观测)或者将长数据(一个患者多条观测)转换为宽数据(一个患者一条观测),在R中我们可以利用Reshape2包来实现.在SA ...

  8. loj #2325. 「清华集训 2017」小Y和恐怖的奴隶主

    #2325. 「清华集训 2017」小Y和恐怖的奴隶主 内存限制:256 MiB时间限制:2000 ms标准输入输出 题目类型:传统评测方式:文本比较   题目描述 "A fight? Co ...

  9. [Xcode 实际操作]四、常用控件-(16)为MKMapView指定地理坐标

    目录:[Swift]Xcode实际操作 本文将演示如何自定义地图视图的的地理坐标 在项目导航区,打开视图控制器的代码文件[ViewController.swift] import UIKit //首先 ...

  10. 使用mount命令挂载CDROM

    Linux显示所有的目录都在一个目录树下,而于他们位于哪一个驱动器/硬件无关.在Linux下的磁盘内容作为子目录形式出现的.可移动介质的内容不会自动出现在这些自目录的,我们必须通过挂载驱动器来实现. ...