前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >优雅简单玩转python3异步并发

优雅简单玩转python3异步并发

作者头像
超级大猪
发布2023-01-30 15:55:57
9500
发布2023-01-30 15:55:57
举报
文章被收录于专栏:大猪的笔记大猪的笔记

在python3之后,随着async/await引入,异步调用以全新而便捷的方式让人眼前一亮。

首先,尽量用async/await定义协程

这里以使用aiohttp请求网络,async函数中,不要使用blocking io(比如requests,传统的mysql/redis库),否则仍然会阻塞全局。

下面的例子展示如何使用协程方式写一个http get请求

  1. async def get_http(url):
  2. async with aiohttp.ClientSession() as session:
  3. async with session.get(url) as resp:
  4. print("开始运行", url)
  5. js_str = await resp.text()
  6. print(len(js_str))

调用协程

  1. 调用协程并不会立刻得到返回的结果,如果想等待future/task的结果,使用await
  2. 如果想并发执行,并统一处理结果,使用loop.create_task,在创建任务的时候,任务就会执行
  3. task可await, 可先把创建的task保存,再统一await

下面的示例,将以并发调用5次baidu。且只使用一个线程。

  1. async def get_https():
  2. loop = asyncio.get_event_loop()
  3. tasks = []
  4. for i in range(5):
  5. task = loop.create_task(get_http("http://www.baidu.com"))
  6. tasks.append(task)
  7. for task in tasks:
  8. await task

最后,在main函数执行并等待全部任务完成

  1. async def run():
  2. await get_https()
  3. loop = asyncio.get_event_loop()
  4. loop.run_until_complete(run())

用其它可异步的IO(一般和网络相关)替换现有的blocking io的库,如aiomysql aioredis 以及其它以aio开头的库

时至今日,异步io库都已经覆盖主流框架和需求。

使用executor调用同步IO或cpu操作

这是一大创举,这个语法糖太香了。那就是使用loop.run_in_executor,让多线程操作与协程/任务模型无缝衔接起来。

这里举一个栗子,并发调用两次sleep

  1. async def run():
  2. start = time.time()
  3. loop = asyncio.get_event_loop()
  4. # 第一个参数传None,使用默认的线程池,一般为5个线程,一般够用
  5. # 第二个参数是函数,而非函数的执行,这里与create_task不同,create_task传入的是 co(), 这里传入的是fn 没有括号执行。
  6. f1 = loop.run_in_executor(None, lambda: time.sleep(1))
  7. f2 = loop.run_in_executor(None, lambda: time.sleep(1))
  8. await f1 # 仍然可以用await关键字等待结果
  9. await f2
  10. # 耗时1s,说明两个sleep是并发执行的
  11. print(time.time()-start)

有了asyncio和loop,向以前的并发(线程)使用方式说拜拜吧。:)

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2022-12-04 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 首先,尽量用async/await定义协程
  • 调用协程
  • 最后,在main函数执行并等待全部任务完成
  • 使用executor调用同步IO或cpu操作
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档