python异步函数中调用同步函数

异步函数调用同步函数

普通函数里面不能await,只有async函数才能await。也就是说,同步函数执行的时候会阻塞所有协程。

直接调用

如果同步函数执行的时间很短。就直接调用。

在执行器里跑

如果同步函数执行的时间很长,就要让它在另外一个线程跑。
以下代码是让同步函数在默认的线程池里跑。
这是在另外一个线程,不会卡住与我们同一个事件循环的协程们。

    result = await loop.run_in_executor(
            None, blocking_io)
<think>我们正在讨论Python异步函数的不同调用方式。根据用户的问题,他关心的是协程、async、await的使用方式。结合引用内容,我们可以总结出几种调用方式: 1. 直接调用异步函数:这会返回一个协程对象,但不会执行函数体内的代码。 2. 使用await表达式:在另一个异步函数中,使用await来等待协程执行完成,同时会挂起当前协程,直到等待的协程返回结果。 3. 使用asyncio.create_task():将协程包装成一个任务(Task)并提交给事件循环,这样任务会在事件循环中调度执行,而不会阻塞当前协程(调用create_task的协程可以继续执行其他代码,然后在需要的时候再await这个任务)。 4. 使用asyncio.run():这是一个高级函数,用于在非异步环境中运行异步程序。它会创建一个新的事件循环,运行传入的协程,并关闭事件循环。 另外,在引用[3]中提到了一个特殊情况:在FastAPI框架中,直接将异步函数返回给框架(如EventSourceResponse)时,框架内部会处理协程的执行,因此不需要显式使用await。这是因为框架已经集成了事件循环,会自动调度协程。 下面我们详细解释这些调用方式,并给出示例。</think>### Python异步函数调用方式详解 在Python异步编程中,协程(coroutine)通过`async def`定义,其调用方式决定了代码的执行行为。以下是主要调用方式: #### 1. **直接调用(不执行)** ```python async def my_task(): print("任务执行") await asyncio.sleep(1) coroutine = my_task() # 仅返回协程对象 print(coroutine) # 输出: <coroutine object my_task at 0x...> ``` - ❌ **不会执行**函数体代码 - 返回未激活的协程对象[^1] #### 2. **使用`await`(同步式等待)** ```python async def main(): await my_task() # 阻塞当前协程直至完成 print("后续代码") ``` - ✅ **顺序执行**:挂起当前协程,等待任务完成 - 适用于需要即时结果的场景[^2] #### 3. **任务封装(并发执行)** ```python async def main(): task1 = asyncio.create_task(my_task()) # 提交到事件循环 task2 = asyncio.create_task(my_task()) print("任务已提交") # 立即执行 await task1 # 需要时等待结果 await task2 ``` - ✅ **并发执行**:任务在后台运行 - `create_task()`是同步调用,立即返回Task对象[^2] - 通过`await`获取结果 #### 4. **事件循环启动** ```python # 在同步代码中启动 asyncio.run(my_task()) # 创建新事件循环 ``` - ✅ **顶层入口点**:阻塞当前线程直至完成 - 每个`run()`调用独立事件循环[^2] #### 特殊场景:框架自动调度 ```python # 在FastAPI等框架中 @app.route("/") async def handler(): return EventSourceResponse(sse_generator()) # 框架自动驱动协程 ``` - ✅ **无需显式await**:框架集成事件循环 - 协程由框架自动执行[^3] --- ### 核心差异总结 | 调用方式 | 执行时机 | 是否阻塞 | 适用场景 | |-------------------|-------------|----------|----------------------| | 直接调用 | ❌ 不执行 | - | 错误用法 | | `await` | ✅ 立即执行 | 阻塞当前 | 顺序依赖任务 | | `create_task()` | ✅ 后台执行 | 非阻塞 | 并发任务 | | `asyncio.run()` | ✅ 立即执行 | 阻塞线程 | 脚本入口 | | 框架响应器 | ✅ 延迟执行 | 非阻塞 | Web框架回调 | > 关键原则:**协程必须被事件循环驱动**。未提交给事件循环的协程永远不会执行[^1][^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值