• python生成器 协程


    生成器

    参考文章:  协程   gevent

    生成器进阶

    看个例子:

    def gg():
        n=''
        i=0
        while True:
            n=yield i   #通过send传入到n
            if not n:
                pass
            else:
                print 'hehe',n
                i=100   #传进参数n的时候,使得i的值也变化了
            i+=1
    if __name__=='__main__':
        a=gg()
        print a.send(None)
        print a.next()
        print a.send(None)
        print a.send(9)
        print a.next()
        a.close()

    结果:

    /usr/bin/python2.7 /home/dahu/PycharmProjects/SpiderLearning/request_lianxi/t7.thread.4.py
    0
    1
    2
    hehe 9
    101
    102

    可以看出

    • 生成器的send(None)方法等于next()方法,next()方法可以直接替换成for循环
    • 通过send(n)传递参数n进生成器,生成器里面通过yield关键字来获取参数的值

    协程

    我们利用这个特性,来学习一下协程

    #!/usr/bin/python
    # coding=utf-8
    # __author__='dahu'
    # data=2017-
    #多线程更改变量
    import time
    def consumer():
        r = ''
        while True:
            n = yield r
            if not n:
                return
            print('[CONSUMER] Consuming %s...' % n)
            time.sleep(0.5)
            r = '200 OK'
    def produce(c):
        c.next()
        n = 0
        while n < 5:
            n = n + 1
            print('[PRODUCER] Producing %s...' % n)
            r = c.send(n)       #给生成器里传参,同时获取生成器里的值
            print('[PRODUCER] Consumer return: %s' % r)
        c.close()
    if __name__=='__main__':
        c = consumer()
        produce(c)

    结果,

    /usr/bin/python2.7 /home/dahu/PycharmProjects/SpiderLearning/request_lianxi/t7.thread.4.py
    [PRODUCER] Producing 1...
    [CONSUMER] Consuming 1...
    [PRODUCER] Consumer return: 200 OK
    [PRODUCER] Producing 2...
    [CONSUMER] Consuming 2...
    [PRODUCER] Consumer return: 200 OK
    [PRODUCER] Producing 3...
    [CONSUMER] Consuming 3...
    [PRODUCER] Consumer return: 200 OK
    [PRODUCER] Producing 4...
    [CONSUMER] Consuming 4...
    [PRODUCER] Consumer return: 200 OK
    [PRODUCER] Producing 5...
    [CONSUMER] Consuming 5...
    [PRODUCER] Consumer return: 200 OK
    
    Process finished with exit code 0
    View Code

    注意到consumer函数是一个generator(生成器),把一个consumer传入produce后:

    1. 首先调用c.next()启动生成器;

    2. 然后,一旦生产了东西,通过c.send(n)切换到consumer执行;

    3. consumer通过yield拿到消息,处理,又通过yield把结果传回;

    4. produce拿到consumer处理的结果,继续生产下一条消息;

    5. produce决定不生产了,通过c.close()关闭consumer,整个过程结束。

    gevent

    Python通过yield提供了对协程的基本支持,但是不完全。而第三方的gevent为Python提供了比较完善的协程支持。

    gevent是第三方库,通过greenlet实现协程,其基本思想是:

    当一个greenlet遇到IO操作时,比如访问网络,就自动切换到其他的greenlet,等到IO操作完成,再在适当的时候切换回来继续执行。由于IO操作非常耗时,经常使程序处于等待状态,有了gevent为我们自动切换协程,就保证总有greenlet在运行,而不是等待IO。

    由于切换是在IO操作时自动完成,所以gevent需要修改Python自带的一些标准库,这一过程在启动时通过monkey patch完成

    直接看例子:

    #!/usr/bin/python
    #coding=utf-8
    #__author__='dahu'
    #data=2017-
    from gevent import monkey; monkey.patch_all()
    import gevent
    import urllib2
    def f(url):
        print('GET: %s' % url)
        resp = urllib2.urlopen(url)
        data = resp.read()
        print('%d bytes received from %s.' % (len(data), url))
    
    gevent.joinall([
            gevent.spawn(f, 'https://www.cnblogs.com/dahu-daqing/'),
            gevent.spawn(f, 'https://www.liaoxuefeng.com/'),
            gevent.spawn(f, 'https://www.baidu.com/'),
    ])

    结果:  从结果看,3个网络操作是并发执行的,而且结束顺序不同,但只有一个线程。

    /usr/bin/python2.7 /home/dahu/PycharmProjects/SpiderLearning/request_lianxi/t10.gevent.py
    GET: https://www.cnblogs.com/dahu-daqing/
    GET: https://www.liaoxuefeng.com/
    GET: https://www.baidu.com/
    227 bytes received from https://www.baidu.com/.
    38708 bytes received from https://www.liaoxuefeng.com/.
    48289 bytes received from https://www.cnblogs.com/dahu-daqing/.
    
    Process finished with exit code 0
  • 相关阅读:
    Web功能测试常用方法
    linux常用指令集说明
    Linux常用指令集
    Web测试
    APP常用测试方法总结
    软件测试笔试题初级篇
    Java 接口自动化系列--用例类之BaseCase 基础父类
    Java + Selenium 系列之失败操作截图及调用
    Java + Selenium 系列之Allure报告集成
    Java 接口自动化系列--工具类之数据库连接与操作
  • 原文地址:https://www.cnblogs.com/dahu-daqing/p/7413581.html
Copyright © 2020-2023  润新知