#转载请联系

什么是协程呢?

线程包含在进程里面,协程包含在线程里面。协程也是和进程、线程一样,可以实现多任务。协程的切换开销比线程更小,不需要保存和恢复线程的状态。最通俗易懂的说法就是,协程是就是一个可以暂停、可以挂起的函数。

说到可以暂停,可以挂起,我们肯定第一时间想起yield。其实yield生成器就能实现协程。

import time

def work1():
while True:
print("我是任务1")
yield
time.sleep(1) def work2():
while True:
print("我是任务2")
yield
time.sleep(1) w1 = work1() # 取得work1函数的生成器
w2 = work2() # 取得work2函数的生成器 while True:
next(w1)
next(w2) 输出:
我是任务1
我是任务2
我是任务1
我是任务2
我是任务1
我是任务2
......
......
......
......

你看,在一个进程里面,没有开线程,只有一个主进程主线程,也能实现多任务。因此说协程也能实现多任务,实现的方式是通过yield生成器来实现的。我们先唤醒第一个生成器,执行到yield,暂停。然后我们再唤醒第二个生成器,执行到yield,暂停。再唤醒第一个生成器,依次循环。(用while True来实现依次唤醒)

------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

如果你觉得yield太难了,不知道怎么用。那么,你可以用greenlet模块中的greenlet类来实现协程。这个类是对yield的封装,相对而言比较简单。

import time

import greenlet

def work1():
while True:
print("我是任务1")
g2.switch() # 转换到任务2
time.sleep(1) def work2():
while True:
print("我是任务2")
g1.switch() # 转换到任务1
time.sleep(1) g1 = greenlet.greenlet(run=work1)
g2 = greenlet.greenlet(run=work2)
g1.switch() # 转换到任务1,其实就是开始执行任务1的意思 输出:
我是任务1
我是任务2
我是任务1
我是任务2
我是任务1
我是任务2
......
......

greenlet类虽然能实现协程,但是每个任务都要用switch()方法转换到另一个任务。如果很多很多任务,每个任务都要带这么一段代码,是不是很烦。还要考虑切换顺序什么的。所以,greenlet又被封装到gevent模块的spawn类里。

-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

gevent的原理是当一个greenlet遇到IO(指的是input output 输入输出,比如网络、文件操作等)操作时,比如访问网络,就自动切换到其他的greenlet,等到IO操作完成,再在适当的时候切换回来继续执行。由于IO操作非常耗时,经常使程序处于等待状态,有了gevent为我们自动切换协程,就保证总有greenlet在运行,而不是等待IO。这个切换原理是和线程、进程的切换原理是一样的。

import gevent
import time
from gevent import monkey # 这个类一定要这样子导入才能识别! monkey.patch_all() # 如果不打这个补丁的话,系统是识别不了原生python代码的time.sleep的
# 所以就不能按在适当的时候切换任务 def work1(n):
i = 0
while True:
print("我是任务1")
time.sleep(1)
i += 1
if i>n:
break def work2(n):
i = 0
while True:
print("我是任务2")
time.sleep(2)
i += 1
if i>n:
break g1 = gevent.spawn(work1,4) # 开启g1协程,且阻塞主线程,直到g1协成任务执行完毕,再解主线程的阻塞
g2 = gevent.spawn(work2,4)
g1.join()
g2.join()
print("我会在哪里?") 输出:
我是任务1
我是任务2
我是任务1
我是任务2
我是任务1
我是任务1
我是任务2
我是任务1
我是任务2
我是任务2
我会在哪里?

注意点:

1.用gevent创建协程时,如果没有导入monkey模块,打补丁的话,是不能识别原生的python代码的休眠time.sleep的。

2.monkey模块的导入,一定要from gevent import monkey

3.join方法既可以启动协程,又可以阻塞主线程,等到该协程完成任务后再解阻塞。

python特有的协程的更多相关文章

  1. Python中Paramiko协程方式详解

    什么是协程 协程我们可以看做是一种用户空间的线程. 操作系统对齐存在一无所知,需要用户自己去调度. 比如说进程,线程操作系统都是知道它们存在的.协程的话是用户空间的线程,操作系统是不知道的. 为什么要 ...

  2. [转载]Python 3.5 协程究竟是个啥

    http://blog.rainy.im/2016/03/10/how-the-heck-does-async-await-work-in-python-3-5/ [译] Python 3.5 协程究 ...

  3. [译] Python 3.5 协程究竟是个啥

    转自:http://blog.rainy.im/2016/03/10/how-the-heck-does-async-await-work-in-python-3-5/ [译] Python 3.5 ...

  4. python中的协程及实现

    1.协程的概念: 协程是一种用户态的轻量级线程.协程拥有自己的寄存器上下文和栈. 协程调度切换时,将寄存器上下文和栈保存到其他地方,在切换回来的时候,恢复先前保存的寄存器上下文和栈. 因此,协程能保留 ...

  5. Python基础之协程

    阅读目录 一 引子 二 协程介绍 三 Greenlet模块 四 Gevent模块 引子 之前我们学习了线程.进程的概念,了解了在操作系统中 进程是资源分配的最小单位,线程是CPU调度的最小单位. 按道 ...

  6. python线程、协程、I/O多路复用

    目录: 并发多线程 协程 I/O多路复用(未完成,待续) 一.并发多线程 1.线程简述: 一条流水线的执行过程是一个线程,一条流水线必须属于一个车间,一个车间的运行过程就是一个进程(一个进程内至少一个 ...

  7. 协程及Python中的协程

    1 协程 1.1协程的概念 协程,又称微线程,纤程.英文名Coroutine.一句话说明什么是线程:协程是一种用户态的轻量级线程.(其实并没有说明白~) 我觉得单说协程,比较抽象,如果对线程有一定了解 ...

  8. python中和生成器协程相关的yield from之最详最强解释,一看就懂(四)

    如果认真读过上文的朋友,应该已经明白了yield from实现的底层generator到caller的上传数据通道是什么了.本文重点讲yield from所实现的caller到coroutine的向下 ...

  9. python中和生成器协程相关yield from之最详最强解释,一看就懂(二)

    一. 从列表中yield  语法形式:yield from <可迭代的对象实例> python中的列表是可迭代的, 如果想构造一个生成器逐一产生list中元素,按之前的yield语法,是在 ...

随机推荐

  1. [leetcode-646-Maximum Length of Pair Chain]

    You are given n pairs of numbers. In every pair, the first number is always smaller than the second ...

  2. 剑指offer:正则表达式匹配

    目录 题目 解题思路 具体代码 题目 题目链接 剑指offer:正则表达式匹配 题目描述 请实现一个函数用来匹配包括'.'和'*'的正则表达式.模式中的字符.表示任意一个字符,而*表示它前面的字符可以 ...

  3. JAVA课程设计 俄罗斯方块

    俄罗斯方块 可实现功能 1.账号管理:登录.注册 2.游戏实现:移动.旋转.消除方块统计得分.暂停游戏.暂停后继续游戏.此轮游戏未结束开启新一轮游戏.游戏未结束退出游戏. 3.排行榜:按分数排名.按局 ...

  4. lintcode-113-删除排序链表中的重复数字 II

    113-删除排序链表中的重复数字 II 给定一个排序链表,删除所有重复的元素只留下原链表中没有重复的元素. 样例 给出 1->2->3->3->4->4->5-&g ...

  5. C#排序相关算法

    http://www.cnblogs.com/zxjyuan/archive/2010/01/06/1640092.html 冒泡法: Using directivesnamespace Bubble ...

  6. Kafka数据辅助和Failover

    数据辅助与Failover CAP理论(它具有一致性.可用性.分区容忍性) CAP理论:分布式系统中,一致性.可用性.分区容忍性最多只可同时满足两个.一般分区容忍性都要求有保障,因此很多时候在可用性与 ...

  7. delphi数据库进行增加操作时,怎么判断插入的这个值是否已经存在?

    //增 procedure TForm1.btnAddClick(Sender: TObject); begin ADOQuery1.Close; ADOQuery1.SQL.Clear; ADOQu ...

  8. oracle分区技术提高查询效率

    概述: 当表中的数据量不断增大,查询数据的速度就会变慢,应用程序的性能就会下降,这时就应该考虑对表进行分区.表进行分区后,逻辑上表仍然是一张完整的表,只是将表中的数据在物理上存放到多个表空间(物理文件 ...

  9. Mapreduce简要原理与实践

    探索Mapreduce简要原理与实践 目录-探索mapreduce 1.Mapreduce的模型简介与特性?Yarn的作用? 2.mapreduce的工作原理是怎样的? 3.配置Yarn与Mapred ...

  10. 【题解】AHOI2009同类分布

    好开心呀~果然只有不看题解做出来的题目才会真正的有一种骄傲与满足吧ヾ(๑╹◡╹)ノ" 实际上这题只要顺藤摸瓜就可以了.首先按照数位dp的套路,有两维想必是省不掉:1.当前dp到到的位数:2. ...