You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在multiprocessing新进程中调用异步函数?FastAPI Webhook异步任务报错及无输出问题解决

问题分析与解决方案

首先来说第一个错误:RuntimeWarning: coroutine 'loop' was never awaited。这是因为multiprocessing.Process的target参数只接收普通函数,但你传了一个异步协程函数loop。Process只会直接调用这个函数,不会自动处理协程的await逻辑,所以就抛出了这个警告。

你后来改成用preloop包裹asyncio.run(loop(fruit))是正确的思路,但为什么没输出?问题出在同步阻塞的time.sleep彻底破坏了asyncio的事件循环。

asyncio的事件循环是单线程的,一旦你在协程里调用了同步的time.sleep,整个事件循环会被完全卡住,根本没时间去处理其他异步任务。你的loop函数里用了time.sleep(1),这会让事件循环每次都被阻塞1秒,连你用create_task创建的printmessage任务都没机会执行;同样printmessage里的time.sleep(5)也是同步阻塞,就算侥幸执行到了,也会把事件循环卡5秒。

修复后的完整代码

import time
from fastapi import Request, FastAPI
import multiprocessing as mp
import uvicorn
import asyncio

async def printmessage(fruit):
    print(fruit)
    # 把同步的time.sleep换成异步的asyncio.sleep
    await asyncio.sleep(5)

async def loop(fruit):
    while True:
        task = asyncio.create_task(printmessage(fruit))
        # 同样替换成异步sleep
        await asyncio.sleep(1)

def preloop(fruit):
    asyncio.run(loop(fruit))

fruit="apple"

if __name__ == '__main__':
    print("PROGRAM LAUNCH...")
    print("WEBHOOK RECEIVE READY...")
    app = FastAPI()

    @app.post("/webhook")
    async def webhook(request : Request):
        print("WEBHOOK RECEIVED")
        p = mp.Process(target=preloop,args=[fruit])
        p.start()
        print('done')
        return 'WEBHOOK RECEIVED'

为什么这样能解决问题?

  1. 用asyncio.run启动协程:preloop作为普通函数,用asyncio.run(loop(fruit))来正确启动异步事件循环,彻底解决了协程未被await的警告。
  2. 替换同步sleep为异步sleep:await asyncio.sleep()会把当前协程挂起,让事件循环去处理其他任务(比如你创建的printmessage任务),这样loop可以每隔1秒就创建一个新的printmessage任务,完全不用等待之前的任务完成,实现你想要的“无需等待printmessage执行完成即可执行loop下一行”的效果。
  3. 多进程隔离:用multiprocessing.Process启动新进程,避免异步事件循环和FastAPI的主事件循环互相干扰。

这样运行后,你就能看到每1秒打印一次apple的预期输出了。

内容的提问来源于stack exchange,提问作者jguy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.28 17:12:39