zoukankan      html  css  js  c++  java
  • asyncio -- 协程库

    asyncio -- 协程库

    event_loop: 事件循环,相当一个无线循环,将函数注册到这个时间循环中,满足条件时,调用适当的处理方法
        	    每一个线程都有一个事件循环,主线程调用asyncio.get_event_loop()时创建循环,把异步任务放入run_until_complete()方法中,事件循环会安排协同程序的执行
    coroutine: 协程对象类型,将协程对象注册到时间循环中,它会被事件循环调用。可以使用async关键字来定义一个方法,这个方法调用时不会立即执行,而是返回一个协程对象
    task: 任务,对协程对象的进一步封装,包含了任务的各个状态,running,finished等。
        
    # 关键字
    async: 定义一个协程
    await: 用来挂起阻塞方法的执行
    

    例:

    import asyncio
    import time
    
    async def do_task(x):
        print('start....')
        start=time.time()
        await asyncio.sleep(x)  # 也是一个协程
        print('共用时%s'%(time.time() - start))
    loop = asyncio.get_event_loop()
    loop.run_until_complete(do_task(3))
    '''
    结果: 
    start....
    共用时3.0001718997955322
    '''
    

    回调

    # 例如IO操作,需要得到返回的结果,可以往future中添加回调来实现
    import asyncio
    import time
    
    async def do_task(x):
        print('start....')
        start=time.time()
        await asyncio.sleep(x)
        print('共用时%s'%(time.time() - start))
    
    def done_callback(result):   # result相当于一个对象
        print('执行回调函数')
    
    result = asyncio.ensure_future(do_task(3))
    result.add_done_callback(done_callback)
    
    loop = asyncio.get_event_loop()
    loop.run_until_complete(result)
    

    多协程

    # 先把协程存入列表中
    coros = [do_task(1),do_task(2)]
    # 然后把多个协程交给loop
    loop.run_until_complete(asyncio.gather(*coros))
    # 例
    async def do_task(x):
        print('start....')
        start=time.time()
        await asyncio.sleep(x)
        print('共用时%s'%(time.time() - start))
    
    coros = [do_task(2),do_task(3)]
    loop = asyncio.get_event_loop()
    loop.run_until_complete(asyncio.gather(*coros))
    '''
    两个协程并发,结束时间以耗时较长的协程为准
    start....
    start....
    共用时2.0001144409179688
    共用时3.003171682357788
    '''
    

    多协程结果获取

    # 没有loop的情况
    async def do_task(x):
        print('start....')
        start=time.time()
        await asyncio.sleep(x)
        # print('共用时%s'%(time.time() - start))
        return '共用时%s'%(time.time() - start)
    
    futus = [asyncio.ensure_future(do_task(2)),asyncio.ensure_future(do_task(3))]
    loop = asyncio.get_event_loop()
    print(loop.run_until_complete(asyncio.gather(*futus)))
    
    '''
    结果:['共用时2.0001144409179688', '共用时3.003171682357788']
    '''
    # 已经有loop 的情况  ?????
    futus = [asyncio.ensure_future(do_task(2)),asyncio.ensure_future(do_task(3))]
    result = await asyncio.gather(*futus)
    print(str(result))
    

    run_until_complete 和 run_forever

    1. run_until_complete: 执行完立即结束 (内部也是调用run_forever)
    2. run_forever : 执行完程序不结束,除非在协程调用中加 loop.stop()
    
    import asyncio
    import time
    async def task(i):
        start = time.time()
        await asyncio.sleep(3)
        print('耗时%s'%(time.time()-start))
        loop.stop()
    
    loop = asyncio.get_event_loop()
    coro = task(3)
    # loop.run_until_complete(coro)
    asyncio.ensure_future(coro)
    loop.run_forever()   # 协程中加loop.stop()
    
    
    # 多个协程使用 run_forever问题: 第二个协程没完,loop 就停止了
    # 解决: gather 将多个协程合成一个future,添加回调,里面终止loop
    import asyncio
    import time
    async def task(i):
        start = time.time()
        await asyncio.sleep(3)
        print('耗时%s'%(time.time()-start))
    
    def done_callback(loop,futu):
        print('callback 函数')
        loop.stop()
        
    loop = asyncio.get_event_loop()
    futus = asyncio.gather(task(2),task(3))  # 用gather合并
    futus.add_done_callback(functools.partial(done_callback,loop))  # 调价回调
    loop.run_forever()
    

    把容易阻塞的函数task 定义成可调出协程

    # 两次task之间相差4秒
    async def task():
        time.sleep(4)
        return datetime.datetime.now()
    tasks = [
        task(),
        task()
    ]
    loop = asyncio.get_event_loop()
    results = loop.run_until_complete(asyncio.gather(*tasks))
    print(results)
    '''
    结果:
    [datetime.datetime(2019, 10, 24, 15, 8, 26, 758582), datetime.datetime(2019, 10, 24, 15, 8, 22, 758353)]
    '''
    # 把容易阻塞的函数task 定义成可调出协程
    def task():
        time.sleep(4)
        return datetime.datetime.now()
    
    async def fetch_async(func,*args):
        loop = asyncio.get_event_loop()
        future = loop.run_in_executor(None,func,*args)
        result = await future
        return result
    
    tasks = [
        fetch_async(task),
        fetch_async(task)
    ]
    loop = asyncio.get_event_loop()
    results = loop.run_until_complete(asyncio.gather(*tasks))
    print(results)
    
    '''
    结果:两个task 几乎同时结束
    [datetime.datetime(2019, 10, 24, 15, 11, 28, 260963), datetime.datetime(2019, 10, 24, 15, 11, 28, 260963)]
    '''
    

    call_later()

    # call_soon 来调用display_date
    # display_data中用 call_later 每隔一分钟调用dispaly_data,直到条件不满足
    import asyncio
    import datetime
    
    def display_date(end_time, loop):
        print(datetime.datetime.now())
        if (loop.time() + 1.0) < end_time:
            loop.call_later(1, display_date, end_time, loop) # (delay,func,*args)
        else:
            loop.stop()
    loop = asyncio.get_event_loop()
    
    # Schedule the first call to display_date()
    end_time = loop.time() + 5.0
    loop.call_soon(display_date, end_time, loop)
    
    # Blocking call interrupted by loop.stop()
    loop.run_forever()
    loop.close()
    

    其他

    # loop.close
    loop.run_until_complete(do_task(3))
    loop.close()
    loop.run_until_complete(do_task(2))  # 此处异常,loop已经关闭
    
    
  • 相关阅读:
    无语的index hint:手工分配哈希区,5小时不出结果,优化后20分钟
    EL 表达式中自己定义函数
    关于SetCapture() 和 ReleaseCapture()的使用方法
    MySql的like语句中的通配符:百分号、下划线和escape
    字符串匹配之horspool算法(简化的BM算法)
    strcmp函数和strcpy函数
    ehci符合USB2.0,uhci,ohci,
    软件发布版本区别介绍-Alpha,Beta,RC,Release
    Wi-Fi定位,AP定位
    CentOS 启动提示unexpected inconsistency;RUN fsck MANUALLY, ntfs的input/output Error,InPageError c000009c使用chkdsk修复磁盘,12款Linux系统恢复工具
  • 原文地址:https://www.cnblogs.com/Afrafre/p/11798575.html
Copyright © 2011-2022 走看看