This commit is contained in:
estom
2024-06-18 14:52:04 +08:00
parent 3c157dca27
commit b002270ab2

View File

@@ -143,3 +143,122 @@ await asyncio.wait([a(), b()])
```
asyncio.run(main())
```
## 最贱实践
> 一个比较好的实践
### 总结
1. async只是声明了一个函数是可异步的。
2. await关键字是核心所有的await点可以共同调度。await关键字是核心所有的await点可以共同调度。await 调用相当于 协程调度的切入点。只有async函数可以被await调用。
3. 本质上是select/epoll机制与java asyncio一样都是将多个io操作阻塞在同一个进程上通过事件响应处理。
4. asyncio.gather() asyncio.run()用于启动多协程。所以异步函数必须有统一的入口。这两个函数是并发的启动点。如果asyncio 只run了一个async函数即协程则不存在并发。所以一般都是跟循环结合起来进行并发。
5. 异步只有用在io操作上才有意义。async函数表示其内部的执行过程中存在io操作。await调用表示允许在调用过程中终端执行。所以**调用的起点**必然是asyncio.run()运行一组协程(运行时已经决定了启动的协程的数量)。**调用的终点**必然是一个可以await的io操作。在示例程序中一般是asyncio.sleep()模拟一个可以await的io操作
6. 一个优势是避免了回调函数。那我们来拆分下回调函数包括几部分回调前的同步操作执行IO操作可以异步并发IO操作后执行回调函数可以异步并发。那么async await关键字是如何避免回调函数呢使用await调用前的部分可以理解为IO操作前的同步操作。使用await完成了一个比较耗时的IO操作。await之后的代码则相当于回调函数的部分。用于在IO操作完成时进行回调。与直接调用相比就是await调用执行了一个 IO操作并且运行在这个点上进行并发调度。
### 有哪些方式可以实现并发
Python 中执行一个 async 函数(异步函数或协程函数)通常使用以下方法:
1. asyncio.run: 是 Python 3.7 新增加的高级 API用于运行最高级别的异步函数入口点。
```
import asyncio
async def async_function():
# 异步操作
pass
# 运行异步函数
asyncio.run(async_function())
```
2. event_loop.run_until_complete: 这是在 asyncio.run 出现之前的传统方式,你需要手动获取事件循环,然后在事件循环中运行协程。
```
import asyncio
async def async_function():
# 异步操作
pass
# 获取当前事件循环
loop = asyncio.get_event_loop()
# 在事件循环中执行异步函数
loop.run_until_complete(async_function())
# 关闭事件循环(在使用完后需要关闭,尤其在生产环境中)
loop.close()
```
3. asyncio.create_task 或 asyncio.ensure_future: 这些函数可以把一个异步函数封装成一个任务task这个任务会被安排在事件循环中运行。
```
import asyncio
async def async_function():
# 异步操作
pass
async def main():
task = asyncio.create_task(async_function()) # Python 3.7+
# task = asyncio.ensure_future(async_function()) # 兼容性更强的方法
await task
asyncio.run(main())
在异步上下文中使用 await: 可以在一个异步函数内部使用 await 来运行其他的异步函数。
import asyncio
async def async_function():
# 异步操作
pass
async def main():
# 在此调用异步函数
await async_function()
asyncio.run(main())
```
4. 并发运行多个异步函数(使用 async.gather 或 asyncio.wait 等): 当你想同时运行多个异步任务时,可以使用 asyncio.gather() 或 asyncio.wait()。
```
import asyncio
async def async_function_one():
# 异步操作
pass
async def async_function_two():
# 异步操作
pass
async def main():
# 同时运行两个异步函数
await asyncio.gather(
async_function_one(),
async_function_two(),
)
asyncio.run(main())
```
5. 使用异步上下文管理器async with: 如果需要自动管理资源(如打开和关闭连接),可以在 async with 语句中运行异步函数。
```
import asyncio
class AsyncContextManager:
async def __aenter__(self):
# 设置资源
pass
async def __aexit__(self, exc_type, exc, tb):
# 清理资源
pass
async def async_function():
# 异步操作
pass
async def main():
async with AsyncContextManager(): # 可以省略 as var如果不需要变量的话
await async_function()
asyncio.run(main())
```
请注意asyncio.run() 实际上是一个方便的函数,它创建了一个新的事件循环,运行传递给它的协程,然后关闭事件循环。但是,如果你已经在一个异步环境中(比如已经运行在一个事件循环内),你就不能再次使用 asyncio.run()。在那种情况下,你需要使用 await配合 asyncio.create_task() 或者直接等待异步函数。