精华内容
下载资源
问答
  • python协程
    2020-11-24 10:05:36

    Python中的协程和生成器很相似但又稍有不同。主要区别在于:

    生成器是数据的生产者

    协程则是数据的消费者

    首先我们先来回顾下生成器的创建过程。我们可以这样去创建一个生成器:

    def fib():

    a, b = 0, 1

    while True:

    yield a

    a, b = b, a+b

    然后我们经常在for循环中这样使用它:

    for i in fib():

    print i

    这样做不仅快而且不会给内存带来压力,因为我们所需要的值都是动态生成的而不是将他们存储在一个列表中。更概括的说如果现在我们在上面的例子中使用yield便可获得了一个协程。协程会消费掉发送给它的值。Python实现的grep就是个很好的例子:

    def grep(pattern):

    print("Searching for", pattern)

    while True:

    line = (yield)

    if pattern in line:

    print(line)

    等等!yield返回了什么?啊哈,我们已经把它变成了一个协程。它将不再包含任何初始值,相反要从外部传值给它。我们可以通过send()方法向它传值。这有个例子:

    search = grep('coroutine')

    next(search)

    #output: Searching for coroutine

    search.send("I love you")

    search.send("Don't you love me?")

    search.send("I love coroutine instead!")

    #output: I love coroutine instead!

    发送的值会被yield接收。我们为什么要运行next()方法呢?这样做正是为了启动一个协程。就像协程中包含的生成器并不是立刻执行,而是通过next()方法来响应send()方法。因此,你必须通过next()方法来执行yield表达式。

    我们可以通过调用close()方法来关闭一个协程。像这样:

    search = grep('coroutine')

    search.close()

    更多协程相关知识的学习大家可以参考David Beazley的这份精彩演讲。

    更多相关内容
  • 本文实例讲述了python 协程中的迭代器,生成器原理及应用。分享给大家供大家参考,具体如下: 1.迭代器理解 迭代器: 迭代器是访问可迭代对象的工具 迭代器是指用iter(obj)函数返回的对象(实例) 迭代器是指用next(it...
  • 本文实例讲述了Python协程 yield与协程greenlet简单用法。分享给大家供大家参考,具体如下: 协程 协程,又称微线程,纤程。英文名Coroutine。 协程是啥 协程是python个中另外一种实现多任务的方式,只不过比线程更...
  • python协程只能运行在事件循环中,但是一旦事件循环运行,又会阻塞当前任务。所以只能在当前进程中再开一个线程,这个线程的主要任务是运行事件循环,就是event_loop,因为他是一个无限循环,会阻塞当前线程。 放一个...
  • python协程

    千次阅读 2021-10-29 12:57:22
    协程python个中另外一种实现多任务的方式,只不过比线程更小占用更小执行单元(理解为需要的资源)。 为啥说它是一个执行单元,因为它自带CPU上下文。这样只要在合适的时机, 我们可以把一个协程 切换到另一个协程...

    协程

    协程,又称微线程。协程是python个中另外一种实现多任务的方式,只不过比线程更小占用更小执行单元(理解为需要的资源)。 为啥说它是一个执行单元,因为它自带CPU上下文。这样只要在合适的时机, 我们可以把一个协程 切换到另一个协程。 只要这个过程中保存或恢复 CPU上下文那么程序还是可以运行的。

    通俗的理解:在一个线程中的某个函数,可以在任何地方保存当前函数的一些临时变量等信息,然后切换到另外一个函数中执行,注意不是通过调用函数的方式做到的,并且切换的次数以及什么时候再切换到原来的函数都由开发者自己确定

    协程和线程差异

    在实现多任务时, 线程切换从系统层面远不止保存和恢复 CPU上下文这么简单。 操作系统为了程序运行的高效性每个线程都有自己缓存Cache等等数据,操作系统还会帮你做这些数据的恢复操作。 所以线程的切换非常耗性能。但是协程的切换只是单纯的操作CPU的上下文,所以一秒钟切换个上百万次系统都抗的住。

    协程 - yield

    简单实现协程

    import time
    
    def work1():
        while True:
            print("---work1---")
            yield
            time.sleep(0.5)
            
            
    def work2():
        while True:
            print("---work2---")
            yield
            time.sleep(0.5)
             
    def main():
        w1 = work1()
        w2 = work2()
        while True:
            next(w1)
            next(w2)
            
    if __name__ == '__main__':
        main()
    

    运行结果:
    在这里插入图片描述

    协程 - greenlet

    为了更好使用协程来完成多任务,python中的greenlet模块对其封装,从而使得切换任务变的更加简单

    使用 pin install greenlet 命令安装greenlet模块

    import time
    from greenlet import greenlet
    
    
    def test1():
        while True:
            print("---A---")
            gr2.switch()  # 切换到gr2中运行
            time.sleep(0.5)
            
            
    def test2():
        while True:
            print("---B---")
            gr1.switch()
            time.sleep(0.5)
             
    gr1 = greenlet(test1)
    gr2 = greenlet(test2)
    
    
    gr1.switch()
    
    

    运行结果:
    在这里插入图片描述

    协程 - gevent

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

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

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

    安装方法:pip install gevent

    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()
    

    运行结果:
    在这里插入图片描述
    可以看到,3个greenlet是依次运行而不是交替运行

    gevent切换执行

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

    运行结果:
    在这里插入图片描述

    gevent.joinall

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

    运行结果:
    在这里插入图片描述

    给程序打补丁

    from gevent import monkey
    import gevent
    import random
    import time
    
    # 有耗时操作时需要
    monkey.patch_all()  # 将程序中用到的耗时操作的代码,换为gevent中自己实现的模块
    
    def coroutine_work(coroutine_name):
        for i in range(5):
            print(coroutine_name, i)
            time.sleep(random.random())
    
    gevent.joinall([
            gevent.spawn(coroutine_work, "work1"),
            gevent.spawn(coroutine_work, "work2")
    ])
    

    在这里插入图片描述

    进程、线程、协程对比

    请仔细理解如下的通俗描述

    • 有一个老板想要开个工厂进行生产某件商品(例如剪子)
    • 他需要花一些财力物力制作一条生产线,这个生产线上有很多的器件以及材料这些所有的 为了能够生产剪子而准备的资源称之为:进程
    • 只有生产线是不能够进行生产的,所以老板的找个工人来进行生产,这个工人能够利用这些材料最终一步步的将剪子做出来,这个来做事情的工人称之为:线程
    • 这个老板为了提高生产率,想到3种办法:
      • 在这条生产线上多招些工人,一起来做剪子,这样效率是成倍増长,即单进程 多线程方式
      • 老板发现这条生产线上的工人不是越多越好,因为一条生产线的资源以及材料毕竟有限,所以老板又花了些财力物力购置了另外一条生产线,然后再招些工人这样效率又再一步提高了,即多进程 多线程方式
      • 老板发现,现在已经有了很多条生产线,并且每条生产线上已经有很多工人了(即程序是多进程的,每个进程中又有多个线程),为了再次提高效率,老板想了个损招,规定:如果某个员工在上班时临时没事或者再等待某些条件(比如等待另一个工人生产完谋道工序 之后他才能再次工作) ,那么这个员工就利用这个时间去做其它的事情,那么也就是说:如果一个线程等待某些条件,可以充分利用这个时间去做其它事情,其实这就是:协程方式

    简单总结

    • 进程是资源分配的单位
    • 线程是操作系统调度的单位
    • 进程切换需要的资源很最大,效率很低
    • 线程切换需要的资源一般,效率一般(当然了在不考虑GIL的情况下)
    • 协程切换任务资源很小,效率高
    • 多进程、多线程根据cpu核数不一样可能是并行的,但是协程是在一个线程中 所以是并发

    案例

    并发下载:

    from gevent import monkey
    import gevent
    import urllib.request
    
    # 有耗时操作时需要
    monkey.patch_all()
    
    def my_downLoad(url):
        print('GET: %s' % url)
        resp = urllib.request.urlopen(url)
        data = resp.read()
        print('%d bytes received from %s.' % (len(data), url))
    
    gevent.joinall([
            gevent.spawn(my_downLoad, 'http://www.baidu.com/'),
            gevent.spawn(my_downLoad, 'http://www.itcast.cn/'),
            gevent.spawn(my_downLoad, 'http://www.itheima.com/'),
    ])
    

    运行结果:
    在这里插入图片描述
    从上能够看到是先发送的获取baidu的相关信息,然后依次是itcast、itheima,但是收到数据的先后顺序不一定与发送顺序相同,这也就体现出了异步,即不确定什么时候会收到数据,顺序不一定

    实现多个视频下载

    from gevent import monkey
    import gevent
    import urllib.request
    
    #有IO才做时需要这一句
    monkey.patch_all()
    
    def my_downLoad(file_name, url):
        print('GET: %s' % url)
        resp = urllib.request.urlopen(url)
        data = resp.read()
    
        with open(file_name, "wb") as f:
            f.write(data)
    
        print('%d bytes received from %s.' % (len(data), url))
    
    gevent.joinall([
            gevent.spawn(my_downLoad, "1.mp4", 'http://oo52bgdsl.bkt.clouddn.com/05day-08-%E3%80%90%E7%90%86%E8%A7%A3%E3%80%91%E5%87%BD%E6%95%B0%E4%BD%BF%E7%94%A8%E6%80%BB%E7%BB%93%EF%BC%88%E4%B8%80%EF%BC%89.mp4'),
            gevent.spawn(my_downLoad, "2.mp4", 'http://oo52bgdsl.bkt.clouddn.com/05day-03-%E3%80%90%E6%8E%8C%E6%8F%A1%E3%80%91%E6%97%A0%E5%8F%82%E6%95%B0%E6%97%A0%E8%BF%94%E5%9B%9E%E5%80%BC%E5%87%BD%E6%95%B0%E7%9A%84%E5%AE%9A%E4%B9%89%E3%80%81%E8%B0%83%E7%94%A8%28%E4%B8%8B%29.mp4'),
    ])
    
    展开全文
  • Python 协程并发

    2020-12-21 21:10:44
    文章目录先行内容同步和异步阻塞和非阻塞并行和并发协作式多任务和抢占式多任务线程正文协程可等待对象一个协程并发执行的例子协程的逻辑扩展内容生成器参考 先行内容 同步和异步 同步和异步关注的发送方和接收方...
  • 浅谈Python协程

    2020-09-16 16:36:56
    主要介绍了Python协程的的相关资料,文中讲解非常细致,代码帮助大家更好的理解和学习,感兴趣的朋友可以了解下
  • 从句法上看,协程与生成器类似,都是定义体中包含 yield 关键字的函数。可是,在协程中, yield 通常出现在表达式的右边(例如, datum = yield),可以产出值,也可以不产出 —— 如果 yield 关键字后面没有表达式...
  • Python协程

    2021-05-12 11:08:46
    由于GIL的存在,导致Python多线程性能甚至比单线程更糟。 GIL: 全局解释器锁(英语:Global Interpreter Lock,缩写GIL),是计算机程序设计语言解释器用于同步线程的一种机制,它使得任何时刻仅有一个线程在执行。...

    由于GIL的存在,导致Python多线程性能甚至比单线程更糟。

    GIL: 全局解释器锁(英语:Global Interpreter Lock,缩写GIL),是计算机程序设计语言解释器用于同步线程的一种机制,它使得任何时刻仅有一个线程在执行。[1]即便在多核心处理器上,使用 GIL 的解释器也只允许同一时间执行一个线程。

    于是出现了协程(Coroutine)这么个东西。

    协程: 协程,又称微线程,纤程,英文名Coroutine。协程的作用,是在执行函数A时,可以随时中断,去执行函数B,然后中断继续执行函数A(可以自由切换)。但这一过程并不是函数调用(没有调用语句),这一整个过程看似像多线程,然而协程只有一个线程执行.

    协程由于由程序主动控制切换,没有线程切换的开销,所以执行效率极高。对于IO密集型任务非常适用,如果是cpu密集型,推荐多进程+协程的方式。

    在Python3.4之前,官方没有对协程的支持,存在一些三方库的实现,比如gevent和Tornado。3.4之后就内置了asyncio标准库,官方真正实现了协程这一特性。

    而Python对协程的支持,是通过Generator实现的,协程是遵循某些规则的生成器。因此,我们在了解协程之前,我们先要学习生成器。

    生成器(Generator)

    我们这里主要讨论yield和yield from这两个表达式,这两个表达式和协程的实现息息相关。

    • Python2.5中引入yield表达式,参见PEP342
    • Python3.3中增加yield from语法,参见PEP380

    方法中包含yield表达式后,Python会将其视作generator对象,不再是普通的方法。

    yield表达式的使用

    我们先来看该表达式的具体使用:

    def test():
        print("generator start")
        n = 1
        while True:
            yield_expression_value = yield n
            print("yield_expression_value = %d" % yield_expression_value)
            n += 1
    
    
    # ①创建generator对象
    generator = test()
    print(type(generator))
    
    print("\n---------------\n")
    
    # ②启动generator
    next_result = generator.__next__()
    print("next_result = %d" % next_result)
    
    print("\n---------------\n")
    
    # ③发送值给yield表达式
    send_result = generator.send(666)
    print("send_result = %d" % send_result)
    

    输出结果:

    <class 'generator'>
    
    ---------------
    
    generator start
    next_result = 1
    
    ---------------
    
    yield_expression_value = 666
    send_result = 2
    

    方法说明:

    • __next__()方法: 作用是启动或者恢复generator的执行,相当于send(None)
    • send(value)方法:作用是发送值给yield表达式。启动generator则是调用send(None)

    生产者和消费者模型

    上面的例子中,代码中断–>切换执行,体现出了协程的部分特点。

    我们再举一个生产者、消费者的例子,这个例子来自廖雪峰的Python教程

    传统的生产者-消费者模型是一个线程写消息,一个线程取消息,通过锁机制控制队列和等待,但一不小心就可能死锁。

    现在改用协程,生产者生产消息后,直接通过yield跳转到消费者开始执行,待消费者执行完毕后,切换回生产者继续生产,效率极高。

    def consumer():
        print("[CONSUMER] start")
        r = 'start'
        while True:
            n = yield r
            if not n:
                print("n is empty")
                continue
            print("[CONSUMER] Consumer is consuming %s" % n)
            r = "200 ok"
    
    
    def producer(c):
        # 启动generator
        start_value = c.send(None)
        print(start_value)
        n = 0
        while n < 3:
            n += 1
            print("[PRODUCER] Producer is producing %d" % n)
            r = c.send(n)
            print('[PRODUCER] Consumer return: %s' % r)
        # 关闭generator
        c.close()
    
    
    # 创建生成器
    c = consumer()
    # 传入generator
    producer(c)
    

    执行结果:

    [CONSUMER] start
    start
    [PRODUCER] Producer is producing 1
    [CONSUMER] Consumer is consuming 1
    [PRODUCER] Consumer return: 200 ok
    [PRODUCER] Producer is producing 2
    [CONSUMER] Consumer is consuming 2
    [PRODUCER] Consumer return: 200 ok
    [PRODUCER] Producer is producing 3
    [CONSUMER] Consumer is consuming 3
    [PRODUCER] Consumer return: 200 ok
    

    注意到consumer函数是一个generator,把一个consumer传入produce后:

    1. 首先调用c.send(None)启动生成器;
    2. 然后,一旦生产了东西,通过c.send(n)切换到consumer执行;
    3. consumer通过yield拿到消息,处理,又通过yield把结果传回;
    4. produce拿到consumer处理的结果,继续生产下一条消息;
    5. produce决定不生产了,通过c.close()关闭consumer,整个过程结束。

    整个流程无锁,由一个线程执行,produce和consumer协作完成任务,所以称为“协程”,而非线程的抢占式多任务。

    yield from表达式

    Python3.3版本新增yield from语法,新语法用于将一个生成器部分操作委托给另一个生成器。此外,允许子生成器(即yield from后的“参数”)返回一个值,该值可供委派生成器(即包含yield from的生成器)使用。并且在委派生成器中,可对子生成器进行优化。

    我们先来看最简单的应用,例如:

    # 子生成器
    def test(n):
        i = 0
        while i < n:
            yield i
            i += 1
    
    # 委派生成器
    def test_yield_from(n):
        print("test_yield_from start")
        yield from test(n)
        print("test_yield_from end")
    
    
    for i in test_yield_from(3):
        print(i)
    

    输出结果:

    test_yield_from start
    0
    1
    2
    test_yield_from end
    

    这里我们仅仅给这个生成器添加了一些打印,如果是正式的代码中,你可以添加正常的执行逻辑。

    如果上面的test_yield_from函数中有两个yield from语句,将串行执行。比如将上面的test_yield_from函数改写成这样:

    def test_yield_from(n):
        print("test_yield_from start")
        yield from test(n)
        print("test_yield_from doing")
        yield from test(n)
        print("test_yield_from end")
    

    将输出:

    test_yield_from start
    0
    1
    2
    test_yield_from doing
    0
    1
    2
    test_yield_from end
    

    在这里,yield from起到的作用相当于下面写法的简写形式

    for item in test(n):
        yield item
    

    看起来这个yield from也没做什么大不了的事,其实它还帮我们处理了异常之类的。具体可以看stackoverflow上的这个问题:In practice, what are the main uses for the new “yield from” syntax in Python 3.3?

    协程(Coroutine)

    • Python3.4开始,新增了asyncio相关的API,语法使用@asyncio.coroutine和yield from实现协程
    • Python3.5中引入async/await语法,参见PEP492

    我们先来看Python3.4的实现。

    @asyncio.coroutine

    Python3.4中,使用@asyncio.coroutine装饰的函数称为协程。不过没有从语法层面进行严格约束。

    对于Python原生支持的协程来说,Python对协程和生成器做了一些区分,便于消除这两个不同但相关的概念的歧义:

    • 标记了@asyncio.coroutine装饰器的函数称为协程函数,iscoroutinefunction()方法返回True。
    • 调用协程函数返回的对象称为协程对象,iscoroutine()函数返回True。

    举个栗子,我们给上面yield from的demo中添加@asyncio.coroutine:

    import asyncio
    
    ...
    
    @asyncio.coroutine
    def test_yield_from(n):
        ...
    
    # 是否是协程函数
    print(asyncio.iscoroutinefunction(test_yield_from))
    # 是否是协程对象
    print(asyncio.iscoroutine(test_yield_from(3)))
    

    然后,我们来实际使用下@asyncio.coroutine和yield from:

    import asyncio
    
    @asyncio.coroutine
    def compute(x, y):
        print("Compute %s + %s ..." % (x, y))
        yield from asyncio.sleep(1.0)
        return x + y
    
    @asyncio.coroutine
    def print_sum(x, y):
        result = yield from compute(x, y)
        print("%s + %s = %s" % (x, y, result))
    
    loop = asyncio.get_event_loop()
    print("start")
    # 中断调用,直到协程执行结束
    loop.run_until_complete(print_sum(1, 2))
    print("end")
    loop.close()
    

    执行结果:

    start
    Compute 1 + 2 ...
    1 + 2 = 3
    end
    

    print_sum这个协程中调用了子协程compute,它将等待compute执行结束才返回结果。

    这个demo点调用流程如下图:
    在这里插入图片描述
    EventLoop将会把print_sum封装成Task对象

    流程图展示了这个demo的控制流程,不过没有展示其全部细节。比如其中“暂停”的1s,实际上创建了一个future对象, 然后通过BaseEventLoop.call_later()在1s后唤醒这个任务。

    值得注意的是,@asyncio.coroutine将在Python3.10版本中移除。

    async/await

    Python3.5开始引入async/await语法(PEP 492),用来简化协程的使用并且便于理解。

    async/await实际上只是@asyncio.coroutine和yield from的语法糖:

    • 把@asyncio.coroutine替换为async
    • 把yield from替换为await

    即可。

    比如下面的例子:

    import asyncio
    
    
    async def compute(x, y):
        print("Compute %s + %s ..." % (x, y))
        await asyncio.sleep(1.0)
        return x + y
    
    
    async def print_sum(x, y):
        result = await compute(x, y)
        print("%s + %s = %s" % (x, y, result))
    
    
    loop = asyncio.get_event_loop()
    print("start")
    loop.run_until_complete(print_sum(1, 2))
    print("end")
    loop.close()
    

    我们再来看一个asyncio中Future的例子:

    import asyncio
    
    future = asyncio.Future()
    
    
    async def coro1():
        print("wait 1 second")
        await asyncio.sleep(1)
        print("set_result")
        future.set_result('data')
    
    
    async def coro2():
        result = await future
        print(result)
    
    
    loop = asyncio.get_event_loop()
    loop.run_until_complete(asyncio.wait([
        coro1(),
        coro2()
    ]))
    loop.close()
    

    输出结果:

    wait 1 second
    set_result
    data
    

    这里await后面跟随的future对象,协程中yield from或者await后面可以调用future对象,其作用是:暂停协程,直到future执行结束或者返回result或抛出异常。

    而在我们的例子中,await future必须要等待future.set_result(‘data’)后才能够结束。将coro2()作为第二个协程可能体现得不够明显,可以将协程的调用改成这样:

    loop = asyncio.get_event_loop()
    loop.run_until_complete(asyncio.wait([
        # coro1(),
        coro2(),
        coro1()
    ]))
    loop.close()
    

    输出的结果仍旧与上面相同。

    其实,async这个关键字的用法不止能用在函数上,还有async with异步上下文管理器,async for异步迭代器. 对这些感兴趣且觉得有用的可以网上找找资料,这里限于篇幅就不过多展开了。

    参考链接

    Python协程
    廖雪峰的Python教程–协程

    展开全文
  • 分析 分析网站寻找需要的网址 用谷歌浏览器摁F12打开开发者工具,然后打开斗鱼颜值分类的页面,如图: 在里面的请求中,最后发现它是以ajax加载的数据,数据格式为json,如图: ...然后把网址放到浏览器中测试是否...
  • Python 协程简介

    2022-04-21 17:33:27
    文章目录协程介绍Greenlet 模块 协程介绍 协程Coroutine: 是单线程下的并发,又称微线程,纤程。协程是一种用户态的轻量级线程,即协程是由用户 程序自己控制调度的 协程特点: 必须在只有一个单线程里实现并发 ...

    协程介绍

    协程Coroutine: 是单线程下的并发,又称微线程,纤程。协程是一种用户态的轻量级线程,即协程是由用户
    程序自己控制调度的
    
    协程特点:
    	必须在只有一个单线程里实现并发
    	修改共享数据不需加锁
    	用户程序里保存多个控制流的上下文栈
    	附加:一个协程遇到IO操作自动切换到其它协程(用到了gevent模块(select机制))
    	
    
    知道了进程是资源分配的最小单位,线程是CPU调度的最小单位。利用进程和线程算是提高了不少cpu的利用率
    但是对于效率的追求不断提高,基于单线程来实现并发又成为一个新的课题,即只用一个主线程(只利用一个
    cpu)情况下实现并发。这样就可以节省创建线程所消耗的时间。所以有了协程的由来。
    
    在线程遇到I/O操作等阻塞或者占用CPU时间过长时,CPU会切走。但可以通过代码来检测程序的IO操作并自己
    处理,让CPU感觉不到IO的存在从而最大幅度的占用CPU,这就是协程的原理。不过操作系统还是只认识进程和
    线程。
    

    Greenlet 模块

    Gevent 是一个第三方库,可以在pycharm直接下载

    在这里使用的方法:
    	g1=gevent.spawn():创建一个协程对象g1,括号内第一个参数是函数名后面可以是位置实参或关键字
    					  实参,都是传给函数eat的
    	g1.join():等待g1结束
    	gevent.joinall([g1]):等待g1结束
    	g1.value:拿到func1的返回值
    	gevent.sleep(2):模拟gevent可以识别的io阻塞,不会释放GIL锁,而 time.sleep 会释放
    	
    
    代码示例
    
    		from gevent import spawn
    		import time
    		from gevent import monkey;monkey.patch_all()  # 固定编写 用于检测所有的IO操作
    		
    		def play(name):
    		    print('%s play 1' % name)
    		    time.sleep(5)
    		    print('%s play 2' % name)
    		
    		def eat(name):
    		    print('%s eat 1' % name)
    		    time.sleep(3)
    		    print('%s eat 2' % name)
    		
    		start_time = time.time()
    		g1 = spawn(play, 'XWenXiang')  # 创建协程对象
    		g2 = spawn(eat, 'XWenXiang')  # 创建协程对象
    		g1.join()  # 等待检测任务执行完毕
    		g2.join()  # 等待检测任务执行完毕
    		print('总耗时:', time.time() - start_time) 
    
     
    
    1. 示例中导入了模块monkey,可以将这句话当成固定语句记忆,用于检测所有io操作。或者使用        
       gevent.sleep(2)来模拟gevent可以识别的io阻塞。
    2. 如果不使用协程按照串行的方式示例代码需要8秒多才能结束,使用了协程之后代码控制切换,
       让CPU继续执行。也就是在单线程执行并发。
    
    展开全文
  • Python协程安全问题:Context Variables

    千次阅读 2021-12-17 19:28:20
    Python协程安全问题:Context Variables 一、问题: 最近,同事压测遇到奇诡问题,添加好友功能在少量并发压测时没有问题;但是,增加并发压力后,出现增加好友失败。和开发等位问题时,发现是不同用户重复发送同一...
  • python 协程安全理解

    2021-08-09 20:39:05
    python 协程安全理解一 背景二 详情三 总结 一 背景 在 Cpython中,由于GIL的存在,所以一次同时只能有一个线程占用CPU,但是即便如此,python 仍然存在线程不安全问题(下文解答), 但是在python中,协程却是安全的 ...
  • python 协程 gevent

    2021-12-17 22:05:00
    第三方协程模 greenlet模块 示例代码: day12/greenlet_0.py 安装 : sudo pip3 install greenlet 函数 greenlet.greenlet(func) 功能:创建协程对象 参数:协程函数 g.switch() 功能:选择要执行的协程函数 ...
  • Python协程讲解

    2021-11-20 18:34:06
    上篇文章我们说过由于GIL锁的限制,导致Python不能充分利用多线程来实现高并发,在某些情况下使用多线程可能比单线程效率更低,所以Python中出现了协程协程(coroutine)又称微线程,是一中轻量级的线程,它可以在...
  • 基于Python协程技术的LAMOST控制节点分布状态采集与监视系统.pdf
  • Python协程的四种实现方式

    千次阅读 2022-01-08 14:15:44
    Python协程的四种实现方式
  • python协程、协程池、协程锁

    千次阅读 2021-01-22 14:49:20
    如何开启协程 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....
  • python 协程 async/await

    千次阅读 2022-04-21 21:22:09
    python因为自身的GIL的问题导致并发不能像java和C一样,但并不是说Python不能实现并发。常见的有两种: **- 计算密集型 IO密集型** 计算密集型 计算密集型任务的特点是要进行大量的计算,消耗CPU资源,比如计算...
  • 封面图片来源:沙沙野协程协程的概念协程的本质是一条线程分成多份,每一份去执行一段代码 多段代码能够在一条线程之间来回切换如果能够在一段代码执行遇到阻塞的过程中切换到另一段可以执行的代码上,相当于完成了...
  • asyncio协程一、效果演示1.1 正常执行1.2 使用asynico学习使用3.1 事件循环asyncio.wait()3.2 携程函数3.3 await3.4 Task对象 协程 协程(Coroutine),也可以被称为微线程,是一种用户态内的上下文切换技术。...
  • 简单聊聊Python协程

    2021-10-09 00:20:52
    前言今天我们来聊聊Python协程,当Python学习到一定的深度,当你需要对代码进行优化提速时,就避不开异步编程,尤其是现在很多优秀的第三方库都实现了异步编程,这使得我们不得不学习。本人...
  • Python协程与异步编程简述前言一、异步与协程二、协程的实现方式1.yield2.greenlet3.gevent4.asyncio5.async + await 关键字总结 前言 Python作为一门脚本语言,经常用于IO密集型的场合,所以,对于异步编程就有所...
  • 用yield实现python协程

    2021-02-03 01:36:23
    刚刚介绍了pythonyield关键字,趁热打铁,现在来了解一下yield实现协程。引用官方的说法:与线程相比,协程更轻量。一个python线程大概占用8M内存,而一个协程只占用1KB不到内存。协程更适用于IO密集型的应用。当然...
  • 引言目前很多公司选择将python项目使用golang重构,很大一方面原因是因为golang的并发能力,golang自带的语法糖支持使并发编程变的相对简单,也更能充分的使用多核CPU的计算资源。相应的,python长期受制于GIL,无法...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 41,462
精华内容 16,584
关键字:

python协程

友情链接: 实验1 跑马灯实验.zip