diff --git a/Python/python标准库2/9网络和进程通信.md b/Python/python标准库2/9网络和进程通信.md index 1615569b..0c4b393f 100644 --- a/Python/python标准库2/9网络和进程通信.md +++ b/Python/python标准库2/9网络和进程通信.md @@ -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() 或者直接等待异步函数。 \ No newline at end of file