zoukankan      html  css  js  c++  java
  • asyncio

    1,事件循环

    import asyncio
    import time # time.sleep()是同步阻塞的接口,在async中不可以使用
    async def get_html(url):
        print("start get url")
        await asyncio.sleep(2)  # 在协程中不要加传统的等待时间,如果非要加的话,就必须在前面加一个await,表明需要等待它完成
        print("end get url")
    
    if __name__ == "__main__":
        start_time = time.time()
        loop = asyncio.get_event_loop()
        loop.run_until_complete(get_html('www.baidu.com'))
        print(time.time()-start_time)
    
    
    >>>
    start get url
    0.0848842123546
    end get url

    当如果需要多个并发呢?

    #使用asyncio
    import asyncio
    import time # time.sleep()是同步阻塞的接口,在async中不可以使用
    async def get_html(url):
        print("start get url")
        await asyncio.sleep(2)  # 在协程中不要加传统的等待时间,如果非要加的话,就必须在前面加一个await,表明需要等待它完成
        print("end get url")
    
    if __name__ == "__main__":
        start_time = time.time()
        loop = asyncio.get_event_loop()
        tasks = [get_html("http://www.baidu.com") for i in range(10)]
        loop.run_until_complete(asyncio.wait(tasks))
        print(time.time()-start_time)

    最终执行的时间也不过是2s

    但是如果使用的是time.sleep,就不可以达成并发

    一、获取协程的返回值

    import asyncio
    import time
    from functools import partial
    async def get_html(url):
        print("start get url")
        await asyncio.sleep(2)
        return "OK"
    
    def callback(url, future):
        print(url)
        print("send email to zl")
    
    if __name__ == "__main__":
        start_time = time.time()
        loop = asyncio.get_event_loop()
        # get_future = asyncio.ensure_future(get_html("http://www.imooc.com"))  # 和下面方法等效
        task = loop.create_task(get_html("http://www.imooc.com"))  #和上面方法等效,将协程注册到事件循环中
        task.add_done_callback(partial(callback, "http://www.imooc.com"))  # 为什么使用偏函数,因为add_done_callback只能接受函数名,因此使用偏函数
        loop.run_until_complete(task)
       print(get_feture.result())
    print(task.result())

    你可能注意到上面还有一个callback,那这个是干什么用的呢?

    callback:比如在一个URL下载完成之后,给我发送一封邮件,或者是耗时比较长的时候发送邮件

    要注意的是,callback这个函数必须要有参数feture,那如果,我还想继续传参呢?

    就使用partial(偏函数),这个函数可以将callback进行包装,但是callback需要额外传参的时候必须在前面写!,偏函数的返回值是函数名

    """
    Python 偏函数是通过 functools 模块被用户调用。
    偏函数 partial 应用
    
    函数在执行时,要带上所有必要的参数进行调用。但是,有时参数可以在函数被调用之前提前获知。这种情况下,一个函数有一个或多个参数预先就能用上,以便函数能用更少的参数进行调用。
    
    偏函数是将所要承载的函数作为partial()函数的第一个参数,原函数的各个参数依次作为partial()函数后续的参数,除非使用关键字参数。
    
    通过语言描述可能无法理解偏函数是怎么使用的,那么就举一个常见的例子来说明。在这个例子里,我们实现了一个取余函数,对于整数 100,取得对于不同数 m 的 100%m 的余数。
    """
    from functools import partial
     
    def mod( n, m ):
      return n % m
     
    mod_by_100 = partial( mod, 100 )
     
    print mod( 100, 7 )  # 2
    print mod_by_100( 7 )  # 2
    View Code

    wait和 gather

    #wait 和 gather
    import asyncio
    import time
    async def get_html(url):
        print("start get url")
        await asyncio.sleep(2)
        print("end get url")
    
    if __name__ == "__main__":
        start_time = time.time()
        loop = asyncio.get_event_loop()
        tasks = [get_html("http://www.imooc.com") for i in range(10)]
        # loop.run_until_complete(asyncio.gather(*tasks))
        # print(time.time()-start_time)
    
        #gather和wait的区别(优先考虑gather)
        #gather更加high-level
        group1 = [get_html("http://projectsedu.com") for i in range(2)]
        group2 = [get_html("http://www.imooc.com") for i in range(2)]
        group1 = asyncio.gather(*group1)
        group2 = asyncio.gather(*group2)
        group2.cancel()  # 呈批的取消
        loop.run_until_complete(asyncio.gather(group1, group2))
        print(time.time() - start_time)

    协程的暂停:

    首先来看一下:

    # 1. run_until_complete
    import asyncio
    loop = asyncio.get_event_loop()
    loop.run_forever()  #不会停止
    loop.run_until_complete()  # 运行完指定协程后停止
    loop会被放到future中
    取消future(task)

    先看一个例子:

    import asyncio
    import time
    
    async def get_html(sleep_times):
        print("waiting")
        await asyncio.sleep(sleep_times)
        print("done after {}s".format(sleep_times))
    
    
    if __name__ == "__main__":
        task1 = get_html(2)
        task2 = get_html(3)
        task3 = get_html(3)
    
        tasks = [task1, task2, task3]
    
        loop = asyncio.get_event_loop()
      loop.run_until_complete(asyncio.wait(tasks))
    waiting
    waiting
    waiting
    done after 2s
    done after 3s
    done after 3s

    这一个时间循环是没有问题的

    我们现在需要做的是取消

    import asyncio
    import time
    
    async def get_html(sleep_times):
        print("waiting")
        await asyncio.sleep(sleep_times)
        print("done after {}s".format(sleep_times))
    
    
    if __name__ == "__main__":
        task1 = get_html(2)
        task2 = get_html(3)
        task3 = get_html(3)
    
        tasks = [task1, task2, task3]
    
        loop = asyncio.get_event_loop()
    
        try:
            loop.run_until_complete(asyncio.wait(tasks))
        except KeyboardInterrupt as e:
            all_tasks = asyncio.Task.all_tasks()  # 可以获取到所有的task
            for task in all_tasks:
                print("cancel task")
                print(task.cancel())
            loop.stop()
            loop.run_forever()  # 这个很关键,不调用会抛出异常的
        finally:
            loop.close()
  • 相关阅读:
    mysql忘记密码怎么办?
    简单Ztree的实现————不连接数据库版
    正则那些事
    牛逼的OSQL----大数据导入
    从数据库导出数据
    瀑布流动态加载图片
    MVC中使用Ajax提交数据 Jquery Ajax方法传值到action
    励志经典,持续收集ing....
    看世界新闻网的简单实现
    TestList汇总
  • 原文地址:https://www.cnblogs.com/zhoulixiansen/p/11191162.html
Copyright © 2011-2022 走看看