CSDN博客地址

Python-asyncio的使用

async/await是python3.5用于定义协程的关键字,async定义一个协程, await用于挂起阻塞的异步调用接口 Asyncio是单线程的,只有一个主线程,但是可以进行多个不同的(task),这里的任务,就是特殊的future对象. 这些不同的任务,被一个叫做event loop的对象所控制。

官方网站: https://docs.python.org/3/library/asyncio.html

asyncio简单用法

async def get_html(url):
    print("start get url")
    await asyncio.sleep(2)
    print("end get url")

def test_1():
    start_time = time.time()
    loop = asyncio.get_event_loop()
    tasks = [get_html("http://www.baidu.com") for _ in range(10)]
    loop.run_until_complete(asyncio.wait(tasks)) # 接收一个可迭代对象
    loop.close()
    print(time.time() - start_time)

接收返回值

async def get_html1(url):
    print("start get url")
    await asyncio.sleep(2)
    print("end get url")
    return "返回值"
def test_2():
    start_time = time.time()
    loop = asyncio.get_event_loop()
    # 多个请求
    tasks = [asyncio.ensure_future(get_html1("http://www.baidu.com")) for _ in range(10)]
    loop.run_until_complete(asyncio.wait(tasks))
    for task in tasks:
        print(task.result())
    print(time.time() - start_time)
    # 单个请求
    task = asyncio.ensure_future(get_html1("http://www.baidu.com"))
    loop.run_until_complete(task)
    loop.close()
    print(task.result())

gather用法

def test_3():
    loop = asyncio.get_event_loop()
    # gather更高级
    group1 = [get_html('http://www.baidu.com') for i in range(2)]
    group2 = [get_html('http://www.baidu.com+++++') for i in range(2)]
    loop.run_until_complete(asyncio.gather(*group1, *group2))
    group1 = [get_html('http://www.baidu.com') for i in range(2)]
    group2 = [get_html('http://www.baidu.com+++++') for i in range(2)]
    g1 = asyncio.gather(*group1)
    g2 = asyncio.gather(*group2)
    loop.run_until_complete(asyncio.gather(g1, g2))
    loop.close()

回调函数

from functools import partial

def callback1(url, arg ,feture):
    print(url, arg)
    print(f"回调函数结果:{feture.result()}")

def test_4():
    loop = asyncio.get_event_loop()
    task = asyncio.ensure_future(get_html1("http://www.baidu.com"))
    # 回调函数 会把 task 传入到 callback
    # 注意参数位置 task 最后一个传进去的
    task.add_done_callback(partial(callback1, "http://www.baidu.com", "gdwjd"))
    loop.run_until_complete(task)
    print("测试结果", task.result())

取消协程

def test_5():
    tasks = [get_html("http://www.baidu.com") for _ in range(3)]
    loop = asyncio.get_event_loop()
    try:
        loop.run_until_complete(asyncio.wait(tasks))
    except Exception as e:
        all_tasks = asyncio.Task.all_tasks()
        for task in all_tasks:
            print("=====", task.cancel())
        loop.stop()
        loop.run_forever()
    finally:
        loop.close()

协程套协程

import aiohttp
async def get(url, i):
    async with aiohttp.ClientSession() as session:
        async with session.get(url) as res:
            return res.status, i

async def hello(i):
    url = "http://www.taobao.com"
    print(i, url)
    res = await get(url, i)
    print("状态码:", res)

def test_6():
    start = time.time()
    loop = asyncio.get_event_loop()
    tasks = [asyncio.ensure_future(hello(i)) for i in range(50)]
    loop.run_until_complete(asyncio.wait(tasks))
    loop.close()
    print(time.time() - start)

示例:生产者与消费者通信

async def consumer(queue, id):
    while True:
        val = await queue.get()
        print('{} get a val: {}'.format(id, val))
        await asyncio.sleep(1)

async def producer(queue, id):
    for i in range(5):
        val = random.randint(0, 10)
        await queue.put(val)
        print('{} put a val: {}'.format(id, val))
        await asyncio.sleep(1)

async def main():
    queue = asyncio.Queue()
    consumer_1 = asyncio.create_task(consumer(queue, 'consumer_1'))
    consumer_2 = asyncio.create_task(consumer(queue, 'consumer_2'))
    producer_1 = asyncio.create_task(producer(queue, 'producer_1'))
    producer_2 = asyncio.create_task(producer(queue, 'producer_2'))
    # 超过10秒,没有消息过来就会取消协程
    await asyncio.sleep(10)
    consumer_1.cancel()
    consumer_2.cancel()
    await asyncio.gather(consumer_1, consumer_2, producer_1, producer_2, return_exceptions=True)

def test_7():
    start = time.perf_counter()
    asyncio.run(main())
    end = time.perf_counter()
    print(end - start)

 

posted @ 2021-01-06 17:41  Yi_warmth  阅读(812)  评论(0编辑  收藏  举报
CSDN博客地址