设为首页 加入收藏

TOP

Asyncio 协程异步笔记(三)
2023-09-23 15:43:39 】 浏览:172
Tags:Asyncio 程异步
到事件循环的任务列表中,等待事件循环去执行(默认是就绪状态)。 task1 = asyncio.create_task(func()) task2 = asyncio.create_task(fucn()) # 当执行某协程遇到 IO 操作时,会自动化切换执行其它任务。 # 此处的 await 时等待相对应的协程全都执行完毕并获取结果。 result_1 = await task1 result_2 = await task2 print(result_1, result_2) asyncio.run(main())

示例 2(这种代码应用得比较多):

import asyncio

async def func():
    print(1)
    await asyncio.sleep(2)
    print(2)
    return "返回值"

async def main():
    print("main 开始")
    
    # 创建协程任务列表
	task_list = [
        asyncio.create_task(func(), name="n1"),  # 给 task 命名,会在返回集中显示
        asyncio.create_task(func(), name="n2")
    ]
    
	# 不能直接把 task_list 以列表的形式加在 await 之后
    # 注意 await 关键字只接受 coroutine object, task object, future object
    # 此处 done 是一个集合,为 task_list 的返回值
    # pending 在 timeout 不为 None 时有意义,timeout 规定了最长等待时间,
    # 如果超过 timeout,那么还未完成的任务将添加到 pending 中。
	done, pending = await asyncio.wait(task_list, timeout=1)
    print(done)
    

asyncio.run(main())


示例 3:

import asyncio

async def func():
    print(1)
    await asyncio.sleep(2)
    print(2)
    return "返回值"

# 创建协程任务列表
task_list = [
    asyncio.create_task(func(), name="n1"),  # 给 task 命名,会在返回集中显示
    asyncio.create_task(func(), name="n2")
]

done, pending = asyncio.run(asyncio.wait(task_list))
print(done)


注意到以上代码会导致程序报错。原因是:asyncio.create_task() 会将协程对象立即添加到事件循环中,但是,事件循环是在 asyncio.run() 中被创造,因此此时并不存在事件循环。应该如此修改:

import asyncio

async def func():
    print(1)
    await asyncio.sleep(2)
    print(2)
    return "返回值"

# 创建协程对象列表
task_list = [
    func(), 
    func()
]

# 此时 asyncio 会在创建事件循环之后,在内部将 task_list 中的协程对象添加到事件循环中
done, pending = asyncio.run(asyncio.wait(task_list))
print(done)


3.5 Future 对象

Future 类是 Task 类的父类,即 Task 类继承自 Future 类,Task 对象内部 await 结果的处理基于 Future 对象而来。

A Future is a special low-level awaitable object that represents an eventual result of an asynchronous operation.



示例 1:

import asyncio

async def main():
    # 获取当前事件循环
    loop = asyncio.get_running_loop()
    
    # 创建一个任务(Future 对象),这个任务什么都不干。
    future = loop.create_future()
    
    # 等待任务最终结果(Future 对象),没有结果则会一直等下去。
    await future
    
asyncio.run(main())

在上述代码中,由于创建的 Future 对象什么也不干,因此 await future 将一直卡住,无法获得返回结果,所以上述代码是没有实际意义的。但注意,如果某一个时刻突然给 future 赋值,那么 future 立刻可以获得返回结果,并且跳出 await



示例 2(没什么意义,用于理解 Future 对象的作用,即帮助我们等待结果):

async def set_after(future):
    await asyncio.sleep(2)
    future.set_result("666")
    
async def main():
    # 获取当前事件循环
    loop = asyncio.get_running_loop()
    
    # 创建一个任务(Future 对象),没有绑定任何行为,则这个任务永远不知道什么时候结束。
    future = loop.create_future()
    
    # 创建一个任务(Task 对象),绑定了 set_after 函数,函数内部在 2s 之后会给 future 赋值。
    # 即手动设置 future 任务的最终结果,那么 future 就可以结束了。
    await loop.create_task(set_after(future))
    
    # 等待 Future 对象获取最终结果,否则一直等待下去。
    data = await future
    print(data)
    
asyncio.run(main())


3.6 concurrent 中的 Future 对象

首先注意到,concurrent 中的 Future 对象(concurrent.futures.Future)和 asyncio 中的 Future 对象没有关系。concurrent 中的 Future 对象是当使用线程池、进程池实现异步操作时使用到的对象。

import time
from concurrent.futures import Future
from concurrent.futures.thread import ThreadPoolExecutor
from concurrent.futures.process import ProcessPoolExecutor

def func(value):
    time.sleep(1)
   	return value
    
# 创建线程池
pool = ThreadPoolExecutor(max_workers=5)

# 或创建进程池
# pool = ProcessPoolExecutor(max_workers=5)

for i in range(10):
    # 让 pool 拿出一个线程去执行 func 函数
    future = pool.submit(func, i)
    print(future)

实际中可能会存在两种 Futu

首页 上一页 1 2 3 4 5 下一页 尾页 3/5/5
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇Python变量:创建、类型、命名规.. 下一篇【matplotlib基础】--几何图形

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目