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

运行中途创建非阻塞并行asyncio任务的标准实现方法

问题背景

我的设计方案如下:

  • 任务1持续休眠并检测来自用户界面的输入;
  • 任务2反复等待温度传感器的输入数据。

目前遇到的问题:用户有时会按下按钮触发一个延后执行的动作,现有相关代码如下:

def completion():
    # do something

async def longtask():
    asyncio.sleep(5)
    completion()

我希望在任务1中实现如下逻辑:

async def task1():
    while True:
        await asyncio.sleep(0.1)
        foo = check_input()
        if foo:
            notawait longtask()
        # other processing

这里的notawait具体含义是:将longtask加入调度队列,但不会暂停task1等待其执行完成;当task1处于休眠状态时,longtask可被调度执行。也就是说在longtask执行结束前,程序中会同时存在3个活跃任务,而非原先的2个。


标准实现方法

使用asyncio.create_task()即可,这是Python 3.7+版本提供的官方标准高层API,专门用于将协程注册到当前运行的事件循环中作为后台任务调度,完全匹配你描述的非阻塞提交需求。

你现有代码存在两处明显问题:

  • longtask()中的asyncio.sleep(5)前缺少await关键字,休眠逻辑不会生效,会直接跳过等待执行completion()
  • 直接调用协程函数只会生成一个未被调度的协程对象,不会进入事件循环执行,必须包装为Task对象才会被调度运行。

修正后的核心代码如下:

import asyncio

def completion():
    # 实际业务逻辑
    pass

async def longtask():
    await asyncio.sleep(5)
    completion()

async def task1():
    while True:
        await asyncio.sleep(0.1)
        foo = check_input()
        if foo:
            # 提交后台任务,不阻塞当前task1执行
            asyncio.create_task(longtask())
        # 其他处理逻辑

行为说明

  • 调用asyncio.create_task(longtask())时,会立刻将longtask包装为Task实例加入事件循环调度队列,当前task1不会在此处暂停,会直接继续执行后续逻辑
  • 当task1执行到下一轮await asyncio.sleep(0.1)让出事件循环控制权时,新建的longtask任务就会被调度执行
  • 只要不主动await这个新建的Task对象,longtask就会和原有的task1、task2以协作式并发的方式运行,运行期间活跃任务数为3,和你的预期完全一致。

注意事项

  • 如果需要捕获后台任务的异常、获取执行结果,可以将create_task返回的Task对象存储到变量/集合中,避免Task被垃圾回收导致意外终止;不需要感知执行结果的场景下可以直接调用不保存返回值
  • Python 3.7之前的版本可以通过获取当前运行的事件循环实例,调用loop.create_task()实现相同效果,目前官方优先推荐直接使用asyncio.create_task()。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 17:57:26