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
相关产品推荐
相关产品推荐

