python - How do I correctly use tasks/the event loop in a discord.py bot?
问题描述
I read the answer here and tried to adapt it for my own usage: How to add a function to discord.py event loop?
My situation is as follows:
I'm developing a discord bot in which I have some commands users can run. These commands have a possibility of erroring, in which case I do client.loop.create_task(errorReportingFunction()) which reports the error to me by messaging me. I also have a command which uses asyncio.create_task() instead.
However I'm having memory leaks which vary from mild to crashing the bot after prolonged usage which leads me to think that I'm not using the tasks system correctly. Should I be cleaning up after the tasks I create and deleting them somehow after I'm done using them? Or is there a system that does that automatically.
I'm also not sure how asyncio.create_task() and client.loop.create_task() differ so I'd appreciate some advice on which to use when, or if they're basically the same.
解决方案
我相信您想要的是在发生错误时做某事(例如发送消息)。如果是这样,在 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')
虽然不和谐机器人的常见做法是有一个错误处理 cog,这将允许您将所有错误处理集中在一个函数中。它可能是这样的:
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}`.\n{permissions}'
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))
推荐阅读
- node.js - 如何从自己的 Schema 方法内部查询 Mongo 集合?
- typescript - 如何以编程方式在组件内部路由 - Vue Router
- linux - 在并发文件中锁定文件
- bash - Bash - for 循环不打印第一个对象
- css - 我可以使用 css-grid 来显示这个布局吗?
- javascript - 如何在 HTML 页面和代码中多次输入相同的数字?
- wicket - 检票口 9:引起:java.io.NotSerializableException:com.my.gui.event.MyEvent
- excel - 如何使用 LEFT 函数将单元格区域的子集复制并粘贴到另一列?
- c - 输入数量
- ssl - 对于需要支持过时系统的网站,Letsencrypt 不再是一种选择,对吧?