asyncio 协程库(常见场景!)
python 的协程:
1,Python对协程的支持是通过generator实现的
2,协程是由程序自身控制的程序间的切换
asyncio 协程库:
1,通过async关键字定义一个协程(coroutine),协程也是一种对象。协程不能直接运行,需要把协程加入到事件循环(loop)
2,所谓task对象是Future类的子类。保存了协程运行后的状态,用于未来获取协程的结果。
3,future: 代表将来执行或没有执行的任务的结果。它和task上没有本质的区别
4,async/await async定义一个协程,await用于挂起阻塞的异步调用接口
5,aiohttp 异步web 请求库
6,aiomysql 异步数据库连接库
常用方法:
import asyncio import time import aiohttp now = lambda: time.time() async def do_some_work(x): print('Waiting: ', x) async with aiohttp.ClientSession() as session: async with session.get('http://www.baidu.com') as resp: print(resp.status) return 'Done after {}s'.format(x) async def main(): coroutine1 = do_some_work(1) coroutine2 = do_some_work(2) coroutine3 = do_some_work(4) tasks = [ # 创建 task 的另一种方式! asyncio.ensure_future(coroutine1), asyncio.ensure_future(coroutine2), asyncio.ensure_future(coroutine3) ] # await 表明 如果遇到阻塞就切换其他的 task # as_completed 返回一个迭代对象 for task in asyncio.as_completed(tasks): result = await task print('Task ret: {}'.format(result)) def callback(t, future): print(t) start = now() # 开启一个无限的循环,程序员会把一些函数注册到事件循环上。 # 当满足事件发生的时候(本次是遇到阻塞),调用相应的协程函数 loop = asyncio.get_event_loop() #将协程变成 task task = loop.create_task(main()) # 获取 task 状态 print(task.result) import functools # 偏函数注册回调参数! task.add_done_callback(functools.partial(callback, 2)) # task 注册到 循环之中 loop.run_until_complete(task) # 将协程函数注册到循环之中(一步到达),等于前两步骤 # loop.run_until_complete(main()) print('TIME: ', now() - start) # 是同步的 1/3 时间消耗
异步操作mysql连接: asyncio + sqlalchemy
1, 创建一个全局的连接池,每个HTTP请求都可以从连接池中直接获取数据库连接。
2, 使用连接池的好处是不必频繁地打开和关闭数据库连接
import aiomysql import asyncio async def select(loop, sql, pool): async with pool.acquire() as conn: async with conn.cursor() as cur: await cur.execute(sql) r = await cur.fetchone() print(r) async def insert(loop, sql, pool): async with pool.acquire() as conn: async with conn.cursor() as cur: await cur.execute(sql) await conn.commit() async def main(loop): pool = await aiomysql.create_pool( host='127.0.0.1', port=3306, user='root', password='123456', db='test', loop=loop) c1 = select(loop=loop, sql='select * from minifw limit 1', pool=pool) c2 = insert(loop=loop, sql="insert into minifw (name) values ('hello')", pool=pool) tasks = [asyncio.ensure_future(c1), asyncio.ensure_future(c2)] return await asyncio.gather(*tasks) if __name__ == '__main__': cur_loop = asyncio.get_event_loop() cur_loop.run_until_complete(main(cur_loop))