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(...)

浙公网安备 33010602011771号