如何在 discord.py 机器人中正确使用任务/事件循环?
Posted
技术标签:
【中文标题】如何在 discord.py 机器人中正确使用任务/事件循环?【英文标题】:How do I correctly use tasks/the event loop in a discord.py bot? 【发布时间】:2021-05-14 19:27:12 【问题描述】:我在这里阅读了答案,并尝试根据自己的使用情况对其进行调整: How to add a function to discord.py event loop?
我的情况如下:
我正在开发一个不和谐的机器人,我可以在其中运行一些用户可以运行的命令。这些命令可能会出错,在这种情况下,我会执行 client.loop.create_task(errorReportingFunction()),它会通过向我发送消息向我报告错误。我还有一个使用 asyncio.create_task() 代替的命令。
但是,我的内存泄漏从轻微到在长时间使用后使机器人崩溃不等,这导致我认为我没有正确使用任务系统。我是否应该在创建任务后进行清理,并在完成使用它们后以某种方式删除它们?或者有没有一个系统可以自动完成。
我也不确定 asyncio.create_task() 和 client.loop.create_task() 有何不同,所以我很感激一些关于何时使用的建议,或者它们是否基本相同。
【问题讨论】:
您为什么要为此使用任务?只在命令函数中运行代码有什么问题? 【参考方案1】:我相信您想要在发生错误时做某事(例如发送消息)。如果是这样,在 discord.py 中有更好的方法来处理这个问题,而不是创建任务。
如果您只想对某个函数进行控制,您可以创建一个错误处理程序来跟踪从该函数引发的错误,并在发生错误时向您发送一条消息:
@bot.command()
async def info(ctx, *, member: discord.Member):
"""Tells you some info about the member."""
fmt = '0 joined on 0.joined_at and has 1 roles.'
await ctx.send(fmt.format(member, len(member.roles)))
@info.error
async def info_error(ctx, error):
if isinstance(error, commands.BadArgument):
await ctx.send('I could not find that member...')
# Send a message to the bot owner about the error
await self.bot.get_user(self.bot.owner_id).send('There has been an error in the command')
虽然 Discord 机器人的一个常见做法是拥有一个错误处理齿轮,它可以让您将所有错误处理集中在一个函数中。可能是这样的:
class ErrorCog(commands.Cog, name='Error'):
'''Cog in charge of the error handling functions.'''
def __init__(self, bot):
self.bot = bot
@commands.Cog.listener()
async def on_command_error(self, ctx, error):
'''Event that takes place when there is an error in a command.
Keyword arguments:
error -- error message '''
error = getattr(error, 'original', error)
# Wrong command
if isinstance(error, commands.CommandNotFound):
message = 'This is not a valid command'
return await ctx.send(message)
# Command is on cooldown
elif isinstance(error, commands.CommandOnCooldown):
if ctx.author.id is self.bot.owner_id:
ctx.command.reset_cooldown(ctx)
return await ctx.command.reinvoke(ctx)
cooldowns =
commands.BucketType.default: f'for the whole bot.',
commands.BucketType.user: f'for you.',
commands.BucketType.guild: f'for this server.',
commands.BucketType.channel: f'for this channel.',
commands.BucketType.member: f'cooldown for you.',
commands.BucketType.category: f'for this channel category.',
commands.BucketType.role: f'for your role.'
return await ctx.send(f'The command `ctx.command` is on cooldown cooldowns[error.cooldown.type] ')
# Bot lacks permissions.
elif isinstance(error, commands.BotMissingPermissions):
permissions = '\n'.join([f'> permission' for permission in error.missing_perms])
message = f'I am missing the following permissions required to run the command `ctx.command`.\npermissions'
try:
return await ctx.send(message)
except discord.Forbidden:
try:
return await ctx.author.send(message)
except discord.Forbidden:
return
# Here you need to add more instances
# of errors according to your needs
def setup(bot):
bot.add_cog(ErrorCog(bot))
【讨论】:
以上是关于如何在 discord.py 机器人中正确使用任务/事件循环?的主要内容,如果未能解决你的问题,请参考以下文章
Discord.py,如果它不存在,我将如何让机器人创建一个频道,但如果它确实存在,它将继续执行它的任务?
Discord.py 带线程,RuntimeError: Timeout context manager 应该在任务内部使用