首页 |  我的博客 |  查看该博主内容分类 | 

asyncio协程相关知识

1.asyncio

旧版
函数装饰器:@asaync.coroutine
IO等待位置:yield from
构造任务列表:ensure_future() ->python3.7前

import asyncio

async def func1():
	...
	await asyncio.slepp(2)
	...
async def func2():
	...
	await asyncio.slepp(2)
	...

tasks = [
	asyncio.ensure_future(func1()),
	asyncio.ensure_future(func2()),
	...
]

执行方法:asyncio.get_event_loop().run_until_complete(asyncio.wait(tasks))

loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.wait(tasks))

# 在python3.7后等价于:
asyncio.run(asyncio.wait(tasks))

2.async & await关键字

python3.5后版本
函数装饰器换做协程函数:async def func(): ...
IO等待位置:await xxx...
执行方法同上。

3.await

await + 可等待的对象(coroutines协程对象(带async的函数)、Future、Task对象 -> IO等待)
简洁版:

import asyncio

async def func():
	...

asyncio.run(func())

嵌套式:

import asyncio

async def others():
	...
	await asyncio.sleep(2)
	...
	
async def func():
	...
	res1 = await others()
	...
	res2 = await others()
	...
	
asyncio.run(func())

4.Task对象

上述只能执行一个,Task可以执行多个任务。
注意:asyncio.create_task()需在python3.7后,3.7前使用低层级的asyncio.ensure_future()

import asyncio

async def func1():
	...
	await asyncio.sleep(2)
	...
	
async def func2():
	...
	await asyncio.sleep(2)
	...
	
tasks = [
	# asyncio.create_task(func1(), name='t1'),
	# asyncio.create_task(func2(), name='t1'),
	func1(),   # 不使用协程函数包裹时写法
	func2(),
	...
]
	
done, pending = asyncio.run(asyncio.wait(tasks))   # timeout可选,结果可在原函数处理,不一定需要返回

5.Future对象 (用于控制结果返回)

Task继承Future,Task对象的await处理基于Future对象

async def set_after(fut):
	await asyncio.sleep(2)
	fut.set_result('666')   # 主要是这个,手动控制返回结果时机

async def main():
	loop = asyncio.get_running_loop()
	fut = loop.create_future()
	await loop.create_task(set_after(fut))
	data = await fut   # 等待set_result()返回结果才继续运行
	print(data)

6.concurrent.future.Future对象 (主要用于线程、进程相结合)

使用线程池、进程池实现异步操作时用到的对象

def func([param1], [param2]):
	...
	
async def main():
	loop = asyncio.get_running_loop()
	# 此处是对线程或进程返回结果进行了Future(async的Future)的转换
	# 第一个参数为None时,为默认loop( asyncio.get_running_loop())
	fut = loop.run_in_executor(进程或线程对象或None, func, [parame1], [param2])
	res = await fut  # 所以才可以await
	print('default thread pool', res)
	# 改写为线程或进程池
	# with concurrent.futures.ThreadPoolExecutor()/ProccessPoolExecutor() as pool:
	# 	res = await loop.run_in_executor(pool, func)
	# 	print('进程/线程 pool', res)
	
asyncio.run(main())

7.asyncio迭代器(不常用)

import asyncio

class Reader:
	''' 自定义异步迭代器(同时也是异步可迭代对象)'''
	def __init(self):
		self.count = 0
		
	async def readline(self):
		self.count += 1
		if self.count == 100:
			return None
		return self.count
		
	def __aiter__(self):
		return self
		
	async def __anext__(self):
		val = await self.readline()
		if val == None:
			raise StopAsyncIteration
		return val
		
async def fun():
	obj = Reader()
	# 不能直接for,需要async定义协程函数,再async for ...
	async for item in obj:
		print(item)
		
asyncio.run(fun())

8.异步上下文管理器

import asyncio

class AsyncContextManager:
	def __init__(self):
		self.conn = conn
		
	async def do_something(self):
		self.conn.execute('xxx')
		return 666
		
	async def __aenter__(self):
		self.conn = xxx
		return self
		
	async def __aexit__(self, exc_type, exc, tb):
		await asyncio.sleep(1)
		
# 不能直接执行,要协程函数包裹
async def func():
	# 支持with的一般都定义了__enter__和__exit__函数
	async with AsyncContextManager() as f:
		res = await f.do_something()
		print(res)

asyncio.run(func())

9.uvloop(提高asyncio效率)

是asyncio的事件循环的替代方案,效率:事件循环>默认asyncio的事件循环

pip install uvloop
import asyncio
import uvloop
# 关键这一句
asyncio.set_event_loop_policy(uvloop.EventPolicy())

# 正常的asyncio代码
...
# 内部的事件循环自动会变为uvloop
asyncio.run(...)
posted @ 2022-09-14 16:20  Z哎呀  阅读(45)  评论(0)    收藏  举报