python 协程 gevent原理与用法分析

本文实例讲述了python 协程 gevent原理与用法。分享给大家供大家参考,具体如下:

gevent

greenlet已经实现了协程,但是这个还的人工切换,是不是觉得太麻烦了,不要捉急,python还有一个比greenlet更强大的并且能够自动切换任务的模块gevent

其原理是当一个greenlet遇到IO(指的是input output 输入输出,比如网络、文件操作等)操作时,比如访问网络,就自动切换到其他的greenlet,等到IO操作完成,再在适当的时候切换回来继续执行。

由于IO操作非常耗时,经常使程序处于等待状态,有了gevent为我们自动切换协程,就保证总有greenlet在运行,而不是等待IO

安装

pip3 install gevent

1. gevent的使用

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)> 1
<Greenlet at 0x10e49f550: f(5)> 2
<Greenlet at 0x10e49f550: f(5)> 3
<Greenlet at 0x10e49f550: f(5)> 4
<Greenlet at 0x10e49f910: f(5)> 0
<Greenlet at 0x10e49f910: f(5)> 1
<Greenlet at 0x10e49f910: f(5)> 2
<Greenlet at 0x10e49f910: f(5)> 3
<Greenlet at 0x10e49f910: f(5)> 4
<Greenlet at 0x10e49f4b0: f(5)> 0
<Greenlet at 0x10e49f4b0: f(5)> 1
<Greenlet at 0x10e49f4b0: f(5)> 2
<Greenlet at 0x10e49f4b0: f(5)> 3
<Greenlet at 0x10e49f4b0: f(5)> 4

可以看到,3个greenlet是依次运行而不是交替运行

2. gevent切换执行

import gevent
def f(n):
  for i in range(n):
    print(gevent.getcurrent(), i)
    #用来模拟一个耗时操作,注意不是time模块中的sleep
    gevent.sleep(1)
g1 = gevent.spawn(f, 5)
g2 = gevent.spawn(f, 5)
g3 = gevent.spawn(f, 5)
g1.join()
g2.join()
g3.join()

运行结果

<Greenlet at 0x7fa70ffa1c30: f(5)> 0
<Greenlet at 0x7fa70ffa1870: f(5)> 0
<Greenlet at 0x7fa70ffa1eb0: f(5)> 0
<Greenlet at 0x7fa70ffa1c30: f(5)> 1
<Greenlet at 0x7fa70ffa1870: f(5)> 1
<Greenlet at 0x7fa70ffa1eb0: f(5)> 1
<Greenlet at 0x7fa70ffa1c30: f(5)> 2
<Greenlet at 0x7fa70ffa1870: f(5)> 2
<Greenlet at 0x7fa70ffa1eb0: f(5)> 2
<Greenlet at 0x7fa70ffa1c30: f(5)> 3
<Greenlet at 0x7fa70ffa1870: f(5)> 3
<Greenlet at 0x7fa70ffa1eb0: f(5)> 3
<Greenlet at 0x7fa70ffa1c30: f(5)> 4
<Greenlet at 0x7fa70ffa1870: f(5)> 4
<Greenlet at 0x7fa70ffa1eb0: f(5)> 4

3. 给程序打补丁

from gevent import monkey
import gevent
import random
import time
def coroutine_work(coroutine_name):
  for i in range(10):
    print(coroutine_name, i)
    time.sleep(random.random())
gevent.joinall([
    gevent.spawn(coroutine_work, "work1"),
    gevent.spawn(coroutine_work, "work2")
])

运行结果

work1 0
work1 1
work1 2
work1 3
work1 4
work1 5
work1 6
work1 7
work1 8
work1 9
work2 0
work2 1
work2 2
work2 3
work2 4
work2 5
work2 6
work2 7
work2 8
work2 9

更多关于Python相关内容感兴趣的读者可查看本站专题:《Python进程与线程操作技巧总结》、《Python数据结构与算法教程》、《Python函数使用技巧总结》、《Python字符串操作技巧汇总》、《Python入门与进阶经典教程》、《Python+MySQL数据库程序设计入门教程》及《Python常见数据库操作技巧汇总》

希望本文所述对大家Python程序设计有所帮助。

(0)

相关推荐

  • Python协程 yield与协程greenlet简单用法示例

    本文实例讲述了Python协程 yield与协程greenlet简单用法.分享给大家供大家参考,具体如下: 协程 协程,又称微线程,纤程.英文名Coroutine. 协程是啥 协程是python个中另外一种实现多任务的方式,只不过比线程更小占用更小执行单元(理解为需要的资源). 为啥说它是一个执行单元,因为它自带CPU上下文.这样只要在合适的时机, 我们可以把一个协程 切换到另一个协程. 只要这个过程中保存或恢复 CPU上下文那么程序还是可以运行的. 通俗的理解:在一个线程中的某个函数,可以在任

  • python中的协程深入理解

    先介绍下什么是协程: 协程,又称微线程,纤程,英文名Coroutine.协程的作用,是在执行函数A时,可以随时中断,去执行函数B,然后中断继续执行函数A(可以自由切换).但这一过程并不是函数调用(没有调用语句),这一整个过程看似像多线程,然而协程只有一个线程执行. 是不是有点没看懂,没事,我们下面会解释.要理解协程是什么,首先需要理解yield,这里简单介绍下,yield可以理解为生成器,yield item这行代码会产出一个值,提供给next(...)的调用方; 此外,还会作出让步,暂停执行生

  • python并发编程之多进程、多线程、异步和协程详解

    最近学习python并发,于是对多进程.多线程.异步和协程做了个总结. 一.多线程 多线程就是允许一个进程内存在多个控制权,以便让多个函数同时处于激活状态,从而让多个函数的操作同时运行.即使是单CPU的计算机,也可以通过不停地在不同线程的指令间切换,从而造成多线程同时运行的效果. 多线程相当于一个并发(concunrrency)系统.并发系统一般同时执行多个任务.如果多个任务可以共享资源,特别是同时写入某个变量的时候,就需要解决同步的问题,比如多线程火车售票系统:两个指令,一个指令检查票是否卖完

  • Python协程操作之gevent(yield阻塞,greenlet),协程实现多任务(有规律的交替协作执行)用法详解

    本文实例讲述了Python 协程操作之gevent(yield阻塞,greenlet),协程实现多任务(有规律的交替协作执行)用法.分享给大家供大家参考,具体如下: 实现多任务:进程消耗的资源最大,线程消耗的资源次之,协程消耗的资源最少(单线程). gevent实现协程,gevent是通过阻塞代码(例如网络延迟等)来自动切换要执行的任务,所以在进行IO密集型程序时(例如爬虫),使用gevent可以提高效率(有效利用网络延迟的时间去执行其他任务). GIL(全局解释器锁)是C语言版本的Python

  • Python协程的用法和例子详解

    从句法上看,协程与生成器类似,都是定义体中包含 yield 关键字的函数.可是,在协程中, yield 通常出现在表达式的右边(例如, datum = yield),可以产出值,也可以不产出 -- 如果 yield 关键字后面没有表达式,那么生成器产出 None. 协程可能会从调用方接收数据,不过调用方把数据提供给协程使用的是 .send(datum) 方法,而不是next(-) 函数. ==yield 关键字甚至还可以不接收或传出数据.不管数据如何流动, yield 都是一种流程控制工具,使用

  • python生成器/yield协程/gevent写简单的图片下载器功能示例

    本文实例讲述了python生成器/yield协程/gevent写简单的图片下载器功能.分享给大家供大家参考,具体如下: 1.生成器: '''第二种生成器''' # 函数只有有yield存在就是生成器 def test(i): while True: i += 1 res = yield i print(res) i += 1 return res def main(): t = test(1) # 创建生成器对象 print(next(t)) # next第一次执行从上到下,yield是终点 p

  • 简单了解python协程的相关知识

    什么是协程 协程是python种一种实现多任务的方式,他是一种比线程更加小的单元,占用更小的执行单元(资源),为啥说他是一个执行单元,因为他自带CPU上下文,这样在合适gr的时机,可以把一个协程切换到另一个协程,只要在这个过程中保存和恢复cpu上下文那么程序还是可以运行的 通俗的理解: 一个线程中的某个函数,可以在任何地方保存当前函数的一些临时变量,然后切换到另一个函数中运行,并且切换的次数以及社么时候再切换回来是可控的 协程和线程的差异 在实现多任务时,线程会自己欢子一些数据,操作系统切换时需

  • 深入浅析python中的多进程、多线程、协程

    进程与线程的历史 我们都知道计算机是由硬件和软件组成的.硬件中的CPU是计算机的核心,它承担计算机的所有任务. 操作系统是运行在硬件之上的软件,是计算机的管理者,它负责资源的管理和分配.任务的调度. 程序是运行在系统上的具有某种功能的软件,比如说浏览器,音乐播放器等. 每次执行程序的时候,都会完成一定的功能,比如说浏览器帮我们打开网页,为了保证其独立性,就需要一个专门的管理和控制执行程序的数据结构--进程控制块. 进程就是一个程序在一个数据集上的一次动态执行过程. 进程一般由程序.数据集.进程控

  • 简述Python中的进程、线程、协程

    进程.线程和协程之间的关系和区别也困扰我一阵子了,最近有一些心得,写一下. 进程拥有自己独立的堆和栈,既不共享堆,亦不共享栈,进程由操作系统调度. 线程拥有自己独立的栈和共享的堆,共享堆,不共享栈,线程亦由操作系统调度(标准线程是的). 协程和线程一样共享堆,不共享栈,协程由程序员在协程的代码里显示调度. 进程和其他两个的区别还是很明显的. 协程和线程的区别是:协程避免了无意义的调度,由此可以提高性能,但也因此,程序员必须自己承担调度的责任,同时,协程也失去了标准线程使用多CPU的能力. Pyt

  • python线程、进程和协程详解

    引言 解释器环境:python3.5.1 我们都知道python网络编程的两大必学模块socket和socketserver,其中的socketserver是一个支持IO多路复用和多线程.多进程的模块.一般我们在socketserver服务端代码中都会写这么一句: server = socketserver.ThreadingTCPServer(settings.IP_PORT, MyServer) ThreadingTCPServer这个类是一个支持多线程和TCP协议的socketserver

  • python编程使用协程并发的优缺点

    协程 协程是一种用户态的轻量级线程,又称微线程. 协程拥有自己的寄存器上下文和栈,调度切换时,将寄存器上下文和栈保存到其他地方,在切回来的时候,恢复先前保存的寄存器上下文和栈.因此:协程能保留上一次调用时的状态(即所有局部状态的一个特定组合),每次过程重入时,就相当于进入上一次调用的状态,换种说法:进入上一次离开时所处逻辑流的位置. 优点: 1.无需线程上下文切换的开销 2.无需原子操作锁定及同步的开销 3.方便切换控制流,简化编程模型 4.高并发+高扩展性+低成本:一个CPU支持上万的协程都不

随机推荐