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

Discord.py提醒命令多时间格式兼容问题求助

解决Discord机器人提醒命令的多时间单位解析与asyncio.gather使用问题

第一步:修改时间解析逻辑,支持多单位组合

现有convert函数仅能处理单一时间单位,我们需要重写它来拆分类似2h42m的字符串,解析每个时间片段并累加总秒数。可以用正则表达式匹配所有数字+单位的组合:

import re
import asyncio
import discord
from discord.ext import commands

class reminder(commands.Cog):
    def __init__(self, client):
        self.client = client

    @commands.Cog.listener()
    async def on_ready(self):
        print('reminder.py is ready!')

    @commands.command()
    async def remind(self, ctx, time_str, *, task):
        def convert(time_str):
            time_dict = {'s': 1, 'm': 60, 'h': 3600, 'd': 86400}
            # 匹配所有数字+单位的片段,比如2h、42m
            matches = re.findall(r'(\d+)([smhd])', time_str.lower())
            if not matches:
                return -1  # 无有效时间片段
            
            total_seconds = 0
            for val_str, unit in matches:
                try:
                    val = int(val_str)
                except ValueError:
                    return -2  # 数字格式错误
                total_seconds += val * time_dict[unit]
            
            return total_seconds

        converted_time = convert(time_str)

        if converted_time == -1:
            await ctx.send('你输入的时间格式不正确,请使用类似2h42m的格式。')
            return
        if converted_time == -2:
            await ctx.send('时间中的数字格式错误,请输入有效数字。')
            return

        await ctx.send(f'已设置提醒:**{time_str}** 后提醒你完成 `{task}`。')

        # 单个提醒任务不需要asyncio.gather,直接sleep即可
        await asyncio.sleep(converted_time)
        await ctx.send(f'{ctx.author.mention} 你的提醒到了:`{task}`!')

async def setup(client):
    await client.add_cog(reminder(client))

第二步:asyncio.gather的实际使用场景

你提到的asyncio.gather主要用于并发执行多个异步任务,比如同时启动多个提醒,或者在等待提醒的同时执行其他异步操作。举个例子,如果要同时设置多个不同时间的提醒,可以这样用:

# 在reminder类中新增多提醒命令
@commands.command()
async def multi_remind(self, ctx, *time_task_pairs):
    # 输入格式示例:-multi_remind 1h "吃饭" 30m "喝水"
    if len(time_task_pairs) % 2 != 0:
        await ctx.send('格式错误,请输入「时间 任务」的成对组合。')
        return

    async def _send_single_remind(delay, task_content):
        await ctx.send(f'已设置提醒:**{delay//3600}h{(delay%3600)//60}m** 后提醒你完成 `{task_content}`。')
        await asyncio.sleep(delay)
        await ctx.send(f'{ctx.author.mention} 你的提醒到了:`{task_content}`!')

    tasks = []
    for i in range(0, len(time_task_pairs), 2):
        time_str = time_task_pairs[i]
        task = time_task_pairs[i+1]
        converted_time = self._convert(time_str)  # 将convert改为类内部方法
        if converted_time < 0:
            await ctx.send(f'时间格式错误:{time_str}')
            return
        tasks.append(_send_single_remind(converted_time, task))
    
    # 用gather并发执行所有提醒任务
    await asyncio.gather(*tasks)

# 把原convert函数改为类内部方法
def _convert(self, time_str):
    time_dict = {'s': 1, 'm': 60, 'h': 3600, 'd': 86400}
    matches = re.findall(r'(\d+)([smhd])', time_str.lower())
    if not matches:
        return -1
    total_seconds = 0
    for val_str, unit in matches:
        try:
            val = int(val_str)
        except ValueError:
            return -2
        total_seconds += val * time_dict[unit]
    return total_seconds

关键说明:

  • 单个提醒任务不需要用asyncio.gather,直接await asyncio.sleep(delay)即可,因为此时只有一个异步等待操作。
  • asyncio.gather(*tasks)会将所有传入的异步任务并发启动,等待所有任务完成后再继续执行后续代码,适合批量处理多个独立的异步任务。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 01:10:28