协程概念-认识asyncio

进程、线程、协程之间的关系

  • 一个进程至少有一个线程,进程里面可以有多个线程
  • 一个线程里面可以有多个协程

进程、线程、线程的对比

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

小结

  • 进程、线程、协程都是可以完成多任务的,可以根据自己实际开发的需要选择使用

  • 由于线程、协程需要的资源很少,所以使用线程和协程的几率最大

  • 开辟协程需要的资源最少

 

 

单事件循环

# 事件循环 + 回调(驱动生成器)+ epoll(IO多路复用)
# asyncio 是python用于解决异步io编程的一整套解决方案

import time
import asyncio


async def get_html(url):
    print("start get url")
    await asyncio.sleep(2)     # 在协程函数里面不能使用普通的time.sleep()
    print("end get url")



if __name__ == '__main__':
    start_time = time.time()
    # 创建一个事件循环器
    loop = asyncio.get_event_loop()
    # 使用以下方法 传入要执行的协程函数
    loop.run_until_complete(get_html("http://www.baidu.com"))
    print(time.time()-start_time)

 

多次并发

import time
import asyncio


async def get_html(url):
    print("start get url")
    await asyncio.sleep(2)     # 在协程函数里面不能使用普通的time.sleep()
    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)

 

获取结果

import time
import asyncio


async def get_html(url):
    print("start get url")
    await asyncio.sleep(2)     # 在协程函数里面不能使用普通的time.sleep()
    print("end get url")
    return "aaa"



if __name__ == '__main__':
    start_time = time.time()
    # 创建一个事件循环器
    loop = asyncio.get_event_loop()

    # 获取结果 示例一
    # get_future=asyncio.ensure_future(get_html("http://www.baidu.com"))
    # loop.run_until_complete(get_future)
    # print(get_future.result())

    # 获取结果 示例二
    task = loop.create_task(get_html("http://www.baidu.com"))
    loop.run_until_complete(task)
    print(task.result())


    print(time.time()-start_time)

 

获取结果

import time
import asyncio
from functools import partial  # 包装函数

async def get_html(url):
    print("start get url")
    await asyncio.sleep(2)     # 在协程函数里面不能使用普通的time.sleep()
    print("end get url")
    return "aaa"


def callback(url,future):  # 这里接受的参数要写在最前面
    print("send email to bobby")
    print(url)



if __name__ == '__main__':
    start_time = time.time()
    # 创建一个事件循环器
    loop = asyncio.get_event_loop()

    # 获取结果 示例一
    # get_future=asyncio.ensure_future(get_html("http://www.baidu.com"))
    # loop.run_until_complete(get_future)
    # print(get_future.result())

    # 获取结果 示例二
    task = loop.create_task(get_html("http://www.baidu.com"))
    # task.add_done_callback(callback)  # 在完成任务 最后再执行
    task.add_done_callback(partial(callback,"http://www.baidu.com"))  # 在完成任务 最后再执行 因为callback只接受函数名 如果想要传递参数需要包装处理 然后要传参数
    loop.run_until_complete(task)
    print(task.result())


    print(time.time()-start_time)

 

gather和wait区别

import time
import asyncio


async def get_html(url):
    print("start get url")
    await asyncio.sleep(2)
    print(url)# 在协程函数里面不能使用普通的time.sleep()
    print("end get url")
    return "aaa"

# gather 和wait区别
# gather 更加高级 可以分组


if __name__ == '__main__':
    start_time = time.time()
    # 创建一个事件循环器
    loop = asyncio.get_event_loop()
    task = [get_html("http://www.baidu.com") for i in range(10)]

    #loop.run_until_complete(asyncio.wait(task))
    # loop.run_until_complete(asyncio.gather(*task))


    # 分组
    # group1 = [get_html("http://www.baidu.com") for i in range(5)]
    # group2 = [get_html("http://www.doubai.com") for i in range(5)]
    # loop.run_until_complete(asyncio.gather(*group1,*group2))
    #
    # 也可以这样写
    group1 = [get_html("http://www.baidu.com") for i in range(5)]
    group2 = [get_html("http://www.doubai.com") for i in range(5)]
    group1 = asyncio.gather(*group1)
    group2 = asyncio.gather(*group2)
    group2.cancel() # 成批取消掉任务
    loop.run_until_complete(asyncio.gather(group1,group2))
    print(time.time()-start_time)

 

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()
#   按ctrl + c 取消task
    try:
        loop.run_until_complete(asyncio.wait(tasks))
    except KeyboardInterrupt as e:
        all_tasks = asyncio.Task.all_tasks()
        for task in all_tasks:
            print("cancel task")
            print(task.cancel())
        loop.stop()
        loop.run_forever()
    finally:
        loop.close()

一些方法

import asyncio


def callback(sleep_times):
    print("sleep {} success".format(sleep_times))

# 停止事件循环
def stoploop(loop):
    loop.stop()



if __name__ == '__main__':
    loop = asyncio.get_event_loop()
    # loop.call_soon(callback,2)    # 在事件循环插入一个函数
    loop.call_later(3, callback,2)  # 在3秒钟后去执行这个函数
    loop.call_soon(callback,4)     # 优先



    now = loop.time()  # loop 内部时间
    loop.call_at(now+2,callback,2)

    # loop.call_soon(stoploop,loop) # 在事件循环插入一个函数
    loop.run_forever()

 

 

借鉴链接:https://juejin.cn/post/6971037591952949256

posted @ 2022-11-14 22:37  钟鼎山林  阅读(22)  评论(0编辑  收藏  举报