优雅简单玩转python3异步并发
2023-06-13 09:16:46 时间
在python3之后,随着async/await引入,异步调用以全新而便捷的方式让人眼前一亮。
首先,尽量用async/await定义协程
这里以使用aiohttp请求网络,async函数中,不要使用blocking io(比如requests,传统的mysql/redis库),否则仍然会阻塞全局。
下面的例子展示如何使用协程方式写一个http get请求
async def get_http(url):
async with aiohttp.ClientSession()
as session:
async with session.get(url)
as resp:
-
print("开始运行", url)
js_str = await resp.text()
-
print(len(js_str))
调用协程
- 调用协程并不会立刻得到返回的结果,如果想等待future/task的结果,使用await
- 如果想并发执行,并统一处理结果,使用loop.create_task,在创建任务的时候,任务就会执行
- task可await, 可先把创建的task保存,再统一await
下面的示例,将以并发调用5次baidu。且只使用一个线程。
async def get_https():
loop = asyncio.get_event_loop()
tasks =
[]
-
for i in range(5):
task = loop.create_task(get_http("http://www.baidu.com"))
tasks.append(task)
-
for task in tasks:
await task
最后,在main函数执行并等待全部任务完成
async def run():
await get_https()
loop = asyncio.get_event_loop()
loop.run_until_complete(run())
用其它可异步的IO(一般和网络相关)替换现有的blocking io的库,如aiomysql aioredis 以及其它以aio开头的库
时至今日,异步io库都已经覆盖主流框架和需求。
使用executor调用同步IO或cpu操作
这是一大创举,这个语法糖太香了。那就是使用loop.run_in_executor
,让多线程操作与协程/任务模型无缝衔接起来。
这里举一个栗子,并发调用两次sleep
async def run():
start = time.time()
loop = asyncio.get_event_loop()
-
# 第一个参数传None,使用默认的线程池,一般为5个线程,一般够用
-
# 第二个参数是函数,而非函数的执行,这里与create_task不同,create_task传入的是 co(), 这里传入的是fn 没有括号执行。
f1 = loop.run_in_executor(None,
lambda: time.sleep(1))
f2 = loop.run_in_executor(None,
lambda: time.sleep(1))
await f1 # 仍然可以用await关键字等待结果
await f2
-
# 耗时1s,说明两个sleep是并发执行的
-
print(time.time()-start)
有了asyncio和loop,向以前的并发(线程)使用方式说拜拜吧。:)
相关文章
- python3获取Elasticsearch数据库数据
- ubuntu安装python3(源码安装方法)
- python3多行注释快捷键_geany注释快捷键
- windows 下使用 python3 复制拷贝图片到剪切板(剪贴板、粘贴板)
- 通过一个小项目介绍Python3读写Access数据库(.mdb)的方法
- Python3 异常: name ‘basestring’ is not defined详解编程语言
- Python3:自动发送账单邮件详解编程语言
- Python3.x:PDFMiner3k在线、本地解析pdf详解编程语言
- python3内置函数回忆详解编程语言
- 在 CentOS 6 系统上安装最新版 Python3 软件包的 3 种方法
- Python3 迭代器与生成器
- Linux 卸载Python3:步骤与注意事项(linux卸载python3)