跳转至

python_协程_async_await新特性

东西都在demo中

import asyncio
import random
import time
from threading import currentThread

animals = ['佩奇', '乔治', '吉吉']


def run_time(func: any) -> any:
    def _():
        st: float = time.time()
        func()
        print('{} 运行用时: {:.2f}秒'.format(func.__name__, time.time() - st))

    return _


@run_time
def demo1():
    def eat(animal: str):
        # 这里模拟吃东西
        t: int = random.randint(1, 2)
        print('{} 开始吃东西'.format(animal))
        time.sleep(t)
        print('{} 花费了{}秒, 吃完东西了'.format(animal, t))

    for animal in animals:
        eat(animal)


@run_time
def demo2():
    async def eat(animal: str):
        # 这里模拟吃东西
        print('{} 开始吃东西'.format(animal))
        t: int = random.randint(1, 2)
        time.sleep(t)
        print('{} 花费了{}秒, 吃完东西了'.format(animal, t))

    for animal in animals:
        eat(animal)


@run_time
def demo3():
    async def eat(animal: str):
        # 这里模拟吃东西
        print('{} 开始吃东西'.format(animal))
        t: int = random.randint(1, 2)
        await time.sleep(t)
        print('{} 花费了{}秒, 吃完东西了'.format(animal, t))

    for animal in animals:
        eat(animal)


@run_time
def demo4():
    async def sleep(_t):
        # 定义一个异步函数用来实现异步操作
        await asyncio.sleep(_t)
        return _t

    async def eat(animal: str) -> str:
        # 这里模拟吃东西
        print('{} 开始吃东西, {}'.format(animal, currentThread()))
        t: int = random.randint(1, 2)
        # 一个异步的函数, 也是可等待的对象
        _t = await sleep(t)
        print('{} 花费了{}秒, 吃完东西了'.format(animal, _t))
        return animal

    # # 执行多个任务
    # # 1. 创建一个事件循环
    # loop = asyncio.get_event_loop()
    # # 2. 加入事件队列
    # tasks:list[any] = []
    # for animal in animals:
    #     tasks.append(eat(animal))
    # # 3. 执行事件队列, 直到最晚的一个事件被处理完毕后结束
    # loop.run_until_complete(asyncio.wait(tasks))

    # # # 获得返回值
    # # 1. 创建一个事件循环
    # loop = asyncio.get_event_loop()
    # # 2. 创建一个事件
    # task = loop.create_task(eat(animals[0]))
    # # 3. 执行事件
    # loop.run_until_complete(task)
    # # 4. 获取事件返回值
    # print(task.result())

    # 获取多个任务返回值(
    # 1. 创建一个事件循环
    loop = asyncio.get_event_loop()
    # 2. 循环创建事件,并加入队列
    tasks: list[any] = []
    for animal in animals:
        task: any = loop.create_task(eat(animal))
        tasks.append(task)
    # 3. 执行事件队列
    loop.run_until_complete(asyncio.wait(tasks))
    # 4. 获得所有事件返回值
    print([i.result() for i in tasks])


if __name__ == '__main__':
    demo4()

    # 假设我们有三个小动物需要吃东西,但是只有一个人来喂食
    # demo1中, 每个小动物在吃完之后才喂下一个小动物吃东西,这叫做(串行),大部分时间都花在挨个等的时间了
    # demo2中, 使用async让函数函数变成异步函数,避免了无谓的等待, 但是却忘了定义喂这个小动物撒完食物之后该什么时候离开(是不是该喂其他小动物了呢?),这样会就造成了还是串行(实际上demo2是无法运行的这里只是比喻)
    # demo3中, 使用await来决定什么时候离开喂养下一个小动物,但是还是和 demo2 一样无法运行, 原因是, await 后面必须跟一个 awaitable 类型或者具有 __await__ 属性的对象. 这个 awaitable, 并不是我们认为 time.sleep() 是 awaitable 就可以 await 了,常见的 awaitable 对象应该是await asyncio.sleep
    # demo4中, 如果调用异步函数, 使用 asyncio 库中的事件循环机制来启动(详情见demo4 详解)