gevent

复习打卡--0826协程、进程池、线程/进程/协程对比

喜夏-厌秋 提交于 2020-02-14 02:17:53
一、协程 协程,又称微线程 协程是python中另外一种实现多任务的方式,只不过比线程更小,占用更小执行单元(理解为需要的资源) 它自带CPU上下文,这样只要在合适的时间,我们就可以把一个协程切换到另一个协程,只要这个过程保存或恢复CPU上下文那么程序还是可以运行的   通俗的理解 在一个线程中的某个函数,可以在任何地方保存当前函数的一些临时变量等信息,然后切换到另外一个函数中执行,注意不是通过调用函数的方式做到的,并且切换的次数以及什么时候再切换到原来的函数都由开发者自己决定   协程和线程差异 在实现多任务时,线程切换从系统层面远不止保存和恢复CPU上下文这么简单,操作系统为了程序的高效性每个线程都有自己缓存Cache等等数据,操作系统还会帮你做这些数据的恢复操作。所以线程的切换比较耗性能。但是协程的切换之间单纯的操作CPU的上下文,所以一秒钟切换个上百万次性能都扛得住。 # 协程的实现: 通过含yield关键字的生成器函数来实现协程 def work1(): for i in range(10): print('---work1获取数据{}'.format(i)) yield i def work2(): for i in range(10) : print('---work2获取数据{}'.format(i)) yield i def main(): g1=work1()

gevent 协程 使用

删除回忆录丶 提交于 2020-02-13 15:31:28
Python通过 yield 提供了对协程的基本支持,但是不完全。而第三方的gevent为Python提供了比较完善的协程支持。 gevent是第三方库,通过greenlet实现协程,其基本思想是: 当一个greenlet遇到IO操作时,比如访问网络,就自动切换到其他的greenlet,等到IO操作完成,再在适当的时候切换回来继续执行。由于IO操作非常耗时,经常使程序处于等待状态,有了gevent为我们自动切换协程,就保证总有greenlet在运行,而不是等待IO。 由于切换是在IO操作时自动完成,所以gevent需要修改Python自带的一些标准库,这一过程在启动时通过monkey patch完成: from gevent import monkey; monkey.patch_socket() import gevent def f(n): for i in range(n): print gevent.getcurrent(), i g1 = gevent.spawn(f, 5) g2 = gevent.spawn(f, 5) g3 = gevent.spawn(f, 5) g1.join() g2.join() g3.join() 运行结果: <Greenlet at 0x10e49f550: f(5)> 0 <Greenlet at 0x10e49f550: f(5)>

python之gevent模块实现协程

烂漫一生 提交于 2020-02-13 09:03:55
Python通过 yield 提供了对协程的基本支持,但是不完全。而第三方的gevent为Python提供了比较完善的协程支持。 gevent是第三方库,通过greenlet实现协程,其基本思想是: 当一个greenlet遇到IO操作时,比如访问网络,就自动切换到其他的greenlet,等到IO操作完成,再在适当的时候切换回来继续执行。由于IO操作非常耗时,经常使程序处于等待状态,有了gevent为我们自动切换协程,就保证总有greenlet在运行,而不是等待IO。 由于切换是在IO操作时自动完成,所以gevent需要修改Python自带的一些标准库,这一过程在启动时通过monkey patch完成: from gevent import monkey; monkey.patch_socket() import gevent def f(n): for i in range(n): print gevent.getcurrent(), i g1 = gevent.spawn(f, 5) g2 = gevent.spawn(f, 5) g3 = gevent.spawn(f, 5) g1.join() g2.join() g3.join() 运行结果: <Greenlet at 0x10e49f550: f(5)> 0 <Greenlet at 0x10e49f550: f(5)>

gevent协程

只愿长相守 提交于 2020-02-13 06:46:19
Python通过 yield 提供了对协程的基本支持,但是不完全。而第三方的gevent为Python提供了比较完善的协程支持。 gevent是第三方库,通过greenlet实现协程,其基本思想是: 当一个greenlet遇到IO操作时,比如访问网络,就自动切换到其他的greenlet,等到IO操作完成,再在适当的时候切换回来继续执行。由于IO操作非常耗时,经常使程序处于等待状态,有了gevent为我们自动切换协程,就保证总有greenlet在运行,而不是等待IO。 由于切换是在IO操作时自动完成,所以gevent需要修改Python自带的一些标准库,这一过程在启动时通过monkey patch完成: 先了解greenlet,这个库用来学习的 功能不是很多。 1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 4 5 from greenlet import greenlet 6 7 8 def test1(): 9 print 12 10 #切换到g2 11 gr2.switch() 12 print 34 13 #切换到g2继续执行上次的任务 14 gr2.switch() 15 16 17 def test2(): 18 print 56 19 gr1.switch() 20 print 78 21 22 gr1 =

Python协程

江枫思渺然 提交于 2020-02-13 05:32:49
一、一些基本概念: 协程(Coroutine),又称微线程,纤程,一种用户级的轻量级线程。 栈(Stack)是一个数据集合,可以理解为只能在一端进行插入或删除操作的列表。 协程拥有自己的寄存器上下文和栈,协程调度切换时,将寄存器上下文和栈保存到其他地方,在切回来的时候,恢复先前保存的寄存器上下文和栈。因此:协程能保留上一次调用时的状态(即所有局部状态的一个特定组合),每次过程重入时,就相当于进入上一次调用的状态。 在并发编程中,协程与线程类似,每个协程表示一个执行单元,有自己的本地数据,与其他协程共享全局数据和其他资源 协程需要用户自己来编写调度逻辑,对于CPU来说,协程其实是单线程,所以cpu不用去考虑怎么调度,切换上下文,这就省去了cpu的切换开销,所以协程一定程度上又好于多线程 协程存在的意义:对于多线程应用,CPU通过切片的方式来切换线程间的执行,线程切换时需要耗时(保存状态,下次继续)。协程,则只使用一个线程,在一个线程中规定某个代码块执行顺序。 协程的适用场景:当程序中存在大量不需要CPU的操作时(IO),适用于协程; 二、yield回顾: def f(): print('ok1') count=yield 5 print(count) print('ok2') yield 6 gen=f() # ret=next(gen) # print(ret) ret=gen

python语法基础-并发编程-协程-长期维护

。_饼干妹妹 提交于 2020-02-10 05:55:57
############### 协程 ############## # 协程 # 小知识点, # 协程和进程和线程一样都是实现并发的手段, # 开启一个线程,创建一个线程,还是需要开销, # 协程 # 协程本质上是一个线程, # 什么是协程:能够在多个任务之间切换来节省一些IO时间, # 不需要再浪费线程之间的切换了,只需要做程序之间的切换, # 程序任务之间的切换也是需要消耗时间,但是开销远远小于进程线程之间的切换, # from greenlet import greenlet # # 这个模块可以实现协程的多个任务的切换, # # 这个greenlet就是真正的协程模块, # # def eat(): # print("eat start") # g2.switch() # print("eat end") # # # def play(): # print("play start") # g1.switch() # print("play end") # # # g1 = greenlet(eat) # 注册, # g2 = greenlet(play) # g1.switch() # 切换 # g2.switch() """ eat start play start eat end play end 这就是实现了协程之间的切换 """ # 我们在工作中会使用进程,线程

服务治理与RPC · 跬步

拈花ヽ惹草 提交于 2020-02-09 09:39:41
以前写过Django中使用zerorpc的方法,但是由于我们的Django是运行在gevent下,而zeromq需要启动一个后台进程处理消息,与gevent使用的greenlet携程是冲突的。 在Java的世界里,Spring Cloud全家桶覆盖了微服务的方方面面,专注于服务治理的框架也有阿里的Dubbo,微博的Motan。但是Python这边没有找到合适的轮子,甚至于好的RPC框架也没有,只有gRPC,Thrift这种跨语言的RPC框架。而这些跨语言的RPC框架基本上也是基于C/C++的Python port。 在github上全局搜索Python rpc,找到一个原生支持gevent的 MPRPC ,而且也找到了微博Motan的Golang版本,所以考虑读Motan-go的源码学习一下什么是服务治理,再基于MPRPC实现自己的轮子。这就有了 doge 。 服务注册 主流的注册中心服务包括etcd,Consul,zookeeper。这里只考虑了etcd与Consul,etcd相对来说简单些,是一个分布式的KV强一致数据库,数据以树状结构存储。Consul的功能更丰富些,有服务的定义,并且支持对服务的健康检查。etcd不支持健康检查,但是可以通过设置key的ttl,然后服务定时刷新ttl来主动上报。 熔断 MPRPC本身提供了一个简单socket pool池

Python全栈(四)高级编程技巧之10.Python多任务-协程

社会主义新天地 提交于 2020-02-07 22:00:53
文章目录 一、生成器-send方法 1.同步、异步 2.堵塞、非堵塞 3.生成器的send()方法 二、使用yield完成多任务和yield from 1.使用yield完成多任务 2.yield from的使用 三、协程-使用greenlet&gevent完成多任务 1.协程概念 2.使用greenlet完成多任务 3.使用gevent完成多任务 4.gevent简单应用 5.进程、线程和协程对比 一、生成器-send方法 1.同步、异步 同步: 是指代码调用 IO操作 时,必须等待IO操作完成才返回的调用方式。 异步: 是指代码调用 IO操作 时,不必等IO操作完成就返回的调用方式。 同步异步比较如下: 2.堵塞、非堵塞 阻塞: 从调用者的角度出发,如果在调用的时候,被卡住,不能再继续向下运行,需要等待,就说是阻塞。 堵塞的例子有: 多个用户同时操作数据库和锁机制 Socket的 accept() 方法 input() 非阻塞: 从调用者的角度出发,如果在调用的时候,没有被卡住,能够继续向下运行,无需等待,就说是非阻塞。 3.生成器的send()方法 之前讲到生成器: def create_fib ( num ) : a , b = 0 , 1 current_num = 0 while current_num < num : yield a a , b = b , a + b

爬虫高性能相关

你离开我真会死。 提交于 2020-02-07 16:30:48
前言 之前讨论过python中多线程和多进程的不同。 由于我们使用的python解释器是Cpython,并不是线程安全的,所以python解释器为了解决这个问题,引入了GIL全局解释器锁。这导致了在同一个进程(一个python解释器下)并不能真正的实现多线程的并行执行,在某一确定的时刻永远只有一个线程在运行。 由此我们可以讨论: 1.当一个程序是I/O密集型时,是该采用多线程还是应该采用多进程? 我们知道当程序进入I/O(阻塞态)时,操作系统会自动剥夺我们程序的CPU使用权。如果我们程序采用多进程,即使给我们的程序分配另外的cpu,操作系统一样会剥夺其对CPU的使用权,这就导致了虽然我们消耗了很多的资源,但几乎对程序的性能没有提升。所以我们应该采用多线程。 2.当一个程序是计算密集型时,是该采用多线程还是应该采用多进程? 计算任务总是由cpu执行,如果我们的计算密集型程序采用多线程,虽然各个计算任务好像在并发执行,但是单位时间内cpu的计算次数是几乎固定的。这就导致了,性能没有额外的提升还额外多了线程之间的切换所带来的开销。 一、同步、异步、回调机制 1.同步调用 import requests def parse_page(res): print('解析 %s' %(len(res))) def get_page(url): print('下载 %s' %url)

day43(协成)

我是研究僧i 提交于 2020-02-04 02:51:18
协程(纤程):一个线程的多个部分。   比线程的单位更小。     在一个线程中可以开启很多协程。   在执行当前操作时,遇到I/O操作就会冻结当前操作,去执行其他任务,不断的检测上一个任务是否 -,如果I/O结束了就继续从冻结的地方开始 I/O操作是不占CPU的 协程的特点:   1.冻结当前程序任务的特点   2.可以规避I/O操作的时间 我们今天顺便讲了生成器,(用时间换了空间,每制造出一个资源就消费一个资源) 好的,!下面正式进入正题???? greenlet 切换(在携程这个模块中做多个协程之间的切换的) from gevent import monkey;monkey.patch_all() # 它会把下面导入的所有的模块中的IO操作都打成一个包,gevent就能够认识这些IO了 import time import gevent # 使用gevent模块来执行多个函数,表示在这些函数遇到IO操作的时候可以在同一个线程中进行切花 # 利用其他任务的IO阻塞时间来切换到其他的任务继续执行 # spawn来发布协程任务 # join负责开启并等待任务执行结束 # gevent本身不认识其他模块中的IO操作,但是如果我们在导入其他模块之前执行from gevent import monkey;monkey.patch_all() #