什么是协程

协程,又称微线程,纤程。英文名Coroutine。一句话说明什么是线程:协程是一种用户态的轻量级线程

协程的特点

协程拥有自己的寄存器上下文和栈。协程调度切换时,将寄存器上下文和栈保存到其他地方,在切回来的时候,恢复先前保存的寄存器上下文和栈。因此:

协程能保留上一次调用时的状态(即所有局部状态的一个特定组合),每次过程重入时,就相当于进入上一次调用的状态,换种说法:进入上一次离开时所处逻辑流的位置。

协程的优点

  • 无需线程上下文切换的开销
  • 无需原子操作锁定及同步的开销

    "原子操作(atomic operation)是不需要synchronized",所谓原子操作是指不会被线程调度机制打断的操作;这种操作一旦开始,就一直运行到结束,中间不会有任何 context switch (切换到另一个线程)。原子操作可以是一个步骤,也可以是多个操作步骤,但是其顺序是不可以被打乱,或者切割掉只执行部分。视作整体是原子性的核心。(因为携程只有一个线程)

  • 方便切换控制流,简化编程模型
  • 高并发+高扩展性+低成本:一个CPU支持上万的协程都不是问题。所以很适合用于高并发处理。(一个进程一个携程,而携程又可以开多个携程,CPU一个核心开一个进程)

协程的缺点

  • 无法利用多核资源:协程的本质是个单线程,它不能同时将 单个CPU 的多个核用上,协程需要和进程配合才能运行在多CPU上.当然我们日常所编写的绝大部分应用都没有这个必要,除非是cpu密集型应用。
  • 进行阻塞(Blocking)操作(如IO时)会阻塞掉整个程序 (携程类似以一个管道,如果一个地方堵住了,那么整个就不通了)

最底层的协程

使用yield实现协程操作例子

一个服务端在创建,而两个客户端在接收。在单线程上几乎同时执行,代码如下:

#客户的方法
def customer(name):
print("===准备买东西===")
while True:
ret = yield
print("名字:%s,买了:%s"%(name,ret)) #服务端
def produce(num):
next(cus1)
next(cus2)
values = 0
while values < num:
values +=1
cus1.send(values)
cus2.send(values) print("谢谢惠顾") if __name__ == "__main__":
cus1 = customer("小明") #创建2个客户端方法的对象
cus2 = customer("小白") produce(5)
#运用生成器的,yield,send,next的特性就可以弄一个最简单的协程

  

Python内部来实现协程的模块gevent

gevent模块不属于Python标准库的模块,要的话得自己下载。下面就让我们看看怎么下载。

我们也可以用greenlet模块实现的协程

greenlet模块也是刚刚在下载gevent模块才有的模块。from greenlet import greenlet ,创建协程对象的方法其实有2个参数“greenlet(run=None,parent = None)”。参数“run”就是要调用的方法,比如下例子中的t1,t2,参数“parent”定义了该协程的父协程,也就是说,greenlet协程直接是可以有父子关系的。如果不设或设为空,则其父协程就是程序默认的“main”主协程。而在要调用的方法,如下面的t1对象中,有一个重要的方法t1.switch(),这个方法的意思就是暂停当前的方法,切换到t1。

实例如下代码

from greenlet import greenlet   #调用模块中的方法

def fun1():
print('a')
t2.switch()
print('b') def fun2():
print('c')
t1.switch()
print('d') t1 = greenlet(fun1) #创建greenlet对象
t2 = greenlet(fun2) t1.switch() #执行t1 #我们可以看到只执行了acb,d并没有执行,因为fun1后面还少了个switch()
#所以可以看出switch还有暂停作用

  

Gevent下所支持的协程

在讲这个之前引进一个内容

猴子补丁 Monkey patching

了实现网络通信的高并发,但是,Gevent直接修改标准库里面大部分的阻塞式系统调用,包括socket、ssl、threading和 select等模块,而变为协作式运行。但是我们无法保证你在复杂的生产环境中有哪些地方使用这些标准库会由于打了补丁而出现奇怪的问题。

一种方法是使用gevent下的socket模块,我们可以通过”from gevent import socket”来导入。不过更常用的方法是使用猴子布丁(Monkey patching)。使用猴子补丁褒贬不一,但是官网上还是建议使用”patch_all()”,而且在程序的第一行就执行。猴子补丁也在Gevent模块的方法中。

Gevent 实现了异步I/O的协程,也就是说只有在遇到I/O阻塞的时候才能切换到其他的方法,而这个I/O阻塞即是可以是执行代码的偶然,也可以是我们定义的必然。

import gevent 这个gevent模块

在看代码之前要知道gevent方法这个对象中的几个方法:

spawn(func,func_args)  func:加入要实现gevent的方法的名字,func_args:方法要传入的参数    创建协程实例

joinall([spawn_list,])    spawn_list:添加入我们刚刚创建的gevent对象              类似于一个同时启动

sleep(time)       time:时间(秒)                           交出CPU控制权限,时间为秒,类似于一个I/O阻塞。这里不能用time.sleep代替

getcurrent()                                         获取当前协程内存地址

下面就让我们来看看例子:

from gevent import monkey   #引入monkey方法

import gevent,time

monkey.patch_all()      #这个在小的协程中体现不出效果,不过建议加下。养成个习惯

def a():
print("1")
gevent.sleep(2) #模拟I/O阻塞2秒
print("2") def b():
print("3")
gevent.sleep(1)
print("4") start = time.time()
gevent.joinall([ #这里必须是个列表
gevent.spawn(a),
gevent.spawn(b),
]
) print(time.time()-start)
#这里可以看到实际上才执行了2秒多一点

  

Python 协程 61的更多相关文章

  1. Python 协程总结

    Python 协程总结 理解 协程,又称为微线程,看上去像是子程序,但是它和子程序又不太一样,它在执行的过程中,可以在中断当前的子程序后去执行别的子程序,再返回来执行之前的子程序,但是它的相关信息还是 ...

  2. day-5 python协程与I/O编程深入浅出

    基于python编程语言环境,重新学习了一遍操作系统IO编程基本知识,同时也学习了什么是协程,通过实际编程,了解进程+协程的优势. 一.python协程编程实现 1.  什么是协程(以下内容来自维基百 ...

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

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

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

  5. 关于python协程中aiorwlock 使用问题

    最近工作中多个项目都开始用asyncio aiohttp aiomysql aioredis ,其实也是更好的用python的协程,但是使用的过程中也是遇到了很多问题,最近遇到的就是 关于aiorwl ...

  6. 用yield实现python协程

    刚刚介绍了pythonyield关键字,趁热打铁,现在来了解一下yield实现协程. 引用官方的说法: 与线程相比,协程更轻量.一个python线程大概占用8M内存,而一个协程只占用1KB不到内存.协 ...

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

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

  8. 00.用 yield 实现 Python 协程

    来源:Python与数据分析 链接: https://mp.weixin.qq.com/s/GrU6C-x4K0WBNPYNJBCrMw 什么是协程 引用官方的说法: 协程是一种用户态的轻量级线程,协 ...

  9. python协程详解

    目录 python协程详解 一.什么是协程 二.了解协程的过程 1.yield工作原理 2.预激协程的装饰器 3.终止协程和异常处理 4.让协程返回值 5.yield from的使用 6.yield ...

随机推荐

  1. 吴裕雄 python 机器学习——分类决策树模型

    import numpy as np import matplotlib.pyplot as plt from sklearn import datasets from sklearn.model_s ...

  2. 使用pycharm 出现 interpreter field is empty 完美解决方法(转载 记录)

    使用pycharm 出现 interpreter field is empty 主要是因为你的电脑没有正确安装python或者安装python出错,重新下载安装覆盖就行 下载安装包:从Python的官 ...

  3. intellij idea在project下同时打开多个工程(maven工程)

    前提:我的工程都是maven工程   我有两个工程,一个是接口contract,一个是接口的具体实现server.想要同时在一个工作空间下展示,方便调试开发,加载后效果如下   idea有worksp ...

  4. Windows防火墙开启ping,禁ping的配置

    当我通过本机Ping另一台在同一局域网内(即在同一网段)的计算机时,发现,如果防火墙开启的话,无论如何也ping不通.一旦关闭防火墙就可以ping通了.这是为什么呢?究竟该怎么设置呢? 原因是这样的, ...

  5. java程序启动redis报错ERR Client sent AUTH, but no password is set

    配置文件中注释掉password一句 重启程序即可

  6. Mac编译RocketMQ 4.1.0

    参考:https://my.oschina.net/jayronwang/blog/861396 1. 前提先安装并设置好maven,jdk,git,这个网上有很多教程,就不讲了 2. 下载rocke ...

  7. 【转载】【吵架】能力 说清自己的能力。表达清楚 ;别人发飙你也要撕b;换位思考,把自己当领导层

    女上司和别人在会议室吵架,大家都说她变态.女人能当好领导吗?  治敏@为好优 2018-06-20 19:56:00 为好优姐姐: 想问问您,是不是职场女强人,都是那种彪悍的战斗机呀! 我刚来公司实习 ...

  8. 2018-2019-2 20165315 《网络对抗技术》Exp3 免杀原理与实践

    2018-2019-2 20165315 <网络对抗技术>Exp3 免杀原理与实践 一.实验内容 正确使用msf编码器,msfvenom生成如jar之类的其他文件,veil-evasion ...

  9. vue iview render里面写时间截取

    render: (h, params) => {params.row.execDate = (params.row.execDate ? params.row.execDate.substr(0 ...

  10. Kubernetes集群升级(kubeadm升级方式)

    1.升级前的版本确认(相同的大版本号下的小版本升级还是跨版本升级) 例如:从1.12.0升级到1.12.7 或者 从1.12.7升级到1.13.0 2.配置kubernetes安装源(已配置kuber ...