• python-48-协程


    前言

    协程:本质上是一个线程能够在多个任务之间切换来节省一些IO时间;

    协程中任务之间的切换也消耗时间,但是开销要远远小于进程线程之间的切换;既是协程任务之间可以通过代码调度切换(但只有协程模块能识别的IO操作才能实现效果)

    一、初识协程

    1、greenlet例子:

    执行A函数切换至B函数执行后,又切换回A函数。一般编程高并发用:进程+线程+协程

    # 一、初识协程:greenlet例子
    # 执行A函数切换至B函数执行后,又切换回A函数。一般编程高并发用:进程+线程+协程
    from greenlet import greenlet
    def func():
        print('func_start')
        r2.switch()                 # 切换到r2,并记录func函数的执行到的位置
        print('func_end')
    def func1():
        print('func1_start')
        r1.switch()                 # 切换到r1,所以最后会打印func_end
        print('func1_end')
    r1=greenlet(func)
    r2=greenlet(func1)
    r1.switch()

    2、gevent:协程

    按正常执行结果会是函数A结束,再运行函数B,但在协程中能够在函数之间切换。

    from gevent import monkey;monkey.patch_all() 必须写上,最后直接写在导入模块前,否则不可识别起不到效果。

    from gevent import monkey;monkey.patch_all()
    import gevent
    import time
    def func():
        print('func_start')
        time.sleep(1)       # 只能导入:monkey;monkey.patch_all() 才能感知
        # gevent.sleep(1)   # 否则用自己的模块的等待
        print('func_end')
    def func1():
        print('func1_start')
        time.sleep(1)
        # gevent.sleep(1)
        print('func1_end')
    r1=gevent.spawn(func)   # 起一个协程任务
    r2=gevent.spawn(func1)  # 起一个协程任务
    r1.join()           # 执行
    r2.join()           # 执行

    3、同步与异步

    # 3、同步与异步
    from gevent import monkey;monkey.patch_all()
    import gevent
    import time
    
    def func():
        time.sleep(1)
        print(666)
    def sync():             # 同步
        for i in range(2):
            func()
    def async():            # 异步
        g_lst=[]
        for i in range(5):
            g=gevent.spawn(func)
            g_lst.append(g)
        gevent.joinall(g_lst)
    sync()
    async()

    4、简单爬虫实例
    ①正常写法,没有协程:

    消耗的时间: 2.069894790649414

    import requests,time
    s=requests.session()
    def get_len(url):
        r=s.get(url)
        return len(r.text)
    
    urls=['https://www.cnblogs.com/gsxl/','http://news.baidu.com/','https://www.baidu.com/',
         'https://daohang.qq.com/?fr=hmpage','https://www.csdn.net/']
    start=time.time()
    for url in urls:
        r=get_len(url)
        print(r)
    t1=time.time()-start
    print('时间:',t1)

    ②运用协程:gevent

    消耗的时间:1.0143725872039795

    # ②运用协程:gevent
    from gevent import monkey;monkey.patch_all()
    import requests,time
    import gevent
    s=requests.session()
    def get_len(url):
        r=s.get(url)
        return len(r.text)
    
    urls=['https://www.cnblogs.com/gsxl/','http://news.baidu.com/','https://www.baidu.com/',
         'https://daohang.qq.com/?fr=hmpage','https://www.csdn.net/']
    r_lst=[]
    start=time.time()
    for url in urls:
        r=gevent.spawn(get_len,url)
        r_lst.append(r)
    gevent.joinall(r_lst)
    for i in r_lst:
        print(i.value)
    t1=time.time()-start
    print(t1

    小结:

    • 进程和线程的任务切换是操作系统调度
    • 协程任务之间可以通过代码调度切换(但只有协程模块能识别的IO操作才能实现效果)

    欢迎来大家QQ交流群一起学习:482713805

  • 相关阅读:
    第 4 章 容器
    第 4 章 容器
    第 4 章 容器
    第 4 章 容器
    第 3 章 镜像
    第 3 章 镜像
    seekbar拖动条控件
    OnClick,onLongClick,OnTouch调用机制
    在TextView文本中实现activity跳转
    TextView显示html图片方法
  • 原文地址:https://www.cnblogs.com/gsxl/p/12593836.html
Copyright © 2020-2023  润新知