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

Python非阻塞式定时器实现问询:避免阻塞其他脚本运行

解决Discord Slash命令定时器阻塞问题

原代码问题分析

你提供的定时器代码使用了同步的time.sleep(1),在异步函数中调用该方法会直接阻塞整个事件循环,导致机器人无法响应其他命令或事件,直到定时器结束。同时代码存在大量重复逻辑,不利于后续维护。

解决方案

通过异步睡眠替代同步睡眠,并重构代码减少冗余,实现非阻塞的定时器功能:

改进后代码

import asyncio
import lightbulb

# 通用定时器逻辑
async def run_timer(ctx, total_minutes: int, notify_interval_sec: int):
    await ctx.respond(f"Timer for {total_minutes} minute⌛ start!")
    await ctx.respond("https://upload.wikimedia.org/wikipedia/commons/7/7a/Alarm_Clock_GIF_Animation_High_Res.gif")
    
    total_seconds = total_minutes * 60
    for second in range(total_seconds):
        await asyncio.sleep(1)  # 异步睡眠,不阻塞事件循环
        # 到达通知间隔且非初始时刻时发送提醒
        if second % notify_interval_sec == 0 and second != 0:
            elapsed_minutes = second // 60
            await ctx.respond(f"{elapsed_minutes} minute⌛ has passed!")
    
    await ctx.respond("Timer ended!")

@my_group.child
@lightbulb.command('five', '5 minute countdown')
@lightbulb.implements(lightbulb.SlashSubCommand)
async def five_minute_timer(ctx):
    await run_timer(ctx, 5, 60)  # 每分钟通知一次

@my_group.child
@lightbulb.command('ten', '10 minute countdown')
@lightbulb.implements(lightbulb.SlashSubCommand)
async def ten_minute_timer(ctx):
    await run_timer(ctx, 10, 60)  # 每分钟通知一次

@my_group.child
@lightbulb.command('thirty', '30 minute countdown')
@lightbulb.implements(lightbulb.SlashSubCommand)
async def thirty_minute_timer(ctx):
    await run_timer(ctx, 30, 300)  # 每5分钟通知一次

关键改进点

  • 替换同步睡眠:用asyncio.sleep(1)替代time.sleep(1),异步睡眠会将控制权交还给事件循环,让机器人可以同时处理其他任务,不会造成阻塞。
  • 代码复用:抽离通用的定时器逻辑到run_timer函数,三个子命令只需传入参数即可,大幅减少重复代码。
  • 保留原有通知逻辑:5/10分钟定时器每分钟通知一次,30分钟定时器每5分钟通知一次,与原需求保持一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 04:26:02