重新加载齿轮后如何防止出现 AttributeError?

时间:2021-04-04 12:35:12

标签: python discord discord.py attributeerror

今天有一个更不寻常的问题,但也许有人可以帮助我。

我正在开发一个机器人,它与音乐有关。以下问题:

如果我更改 cog 中的内容,然后更改 reload 中的内容,我总是会收到特定命令的 AttributeError: 'NoneType' object has no attribute 'XXXX' 错误。 有没有办法解决/防止这种情况?

例如,当机器人处于语音通道中,然后我重新加载 cog 时,就会发生错误。

我为每个与音乐有关的命令查询 state,它可能与此有关吗?

state = self.get_state(ctx.guild)

get_state 的完整功能:

    def get_state(self, guild):
        """Gets the state for `guild`, creating it if it does not exist."""
        if guild.id in self.states:
            return self.states[guild.id]
        else:
            self.states[guild.id] = GuildState()
            return self.states[guild.id]

我尝试try/except AttributeError 解决它,但当然这并没有真正起作用/控制台仍然给了我输出。

这是一个示例代码:

    @commands.command()
    @commands.guild_only()
    @commands.check(audio_playing)
    @commands.check(in_voice_channel)
    @commands.check(is_audio_requester)
    async def loop(self, ctx):
        """Activates/Deactivates the loop for a song."""
        state = self.get_state(ctx.guild)
        status = state.now_playing.toggle_loop()
        if status is None:
            return await ctx.send(
                embed=discord.Embed(title=":no_entry:  Unable to toggle loop.", color=discord.Color.red()))
        else:
            return await ctx.send(embed=discord.Embed(
                title=f":repeat:  Loop: {'**Enabled**' if state.now_playing.loop else '**Disabled**'}.",
                color=self.bot.get_embed_color(ctx.guild)))

如果我在 cog 中进行更改,重新加载它,然后再次尝试运行 loop,我会收到以下错误

In loop:
  File "C:\Users\Dominik\PycharmProjects\AlchiReWrite\venv\lib\site-packages\discord\ext\commands\core.py", line 85, in wrapped
    ret = await coro(*args, **kwargs)
  File "C:\Users\Dominik\PycharmProjects\AlchiReWrite\cogs\music.py", line 220, in loop
    status = state.now_playing.toggle_loop()
AttributeError: 'NoneType' object has no attribute 'toggle_loop'

(所有其他命令的错误相同)

请求,我们有 GuildState 类:

class GuildState:
    """Helper class managing per-guild state."""

    def __init__(self):
        self.volume = 1.0
        self.playlist = []
        self.message_queue = []
        self.skip_votes = set()
        self.now_playing = None
        self.control_message = None
        self.loop = False
        self.skipped = False

    def is_requester(self, user):
        return self.now_playing.requested_by == user

我该如何克服这个错误?

机器人在命令 play URL 上加入,然后我构建了以下内容:

if not state.now_playing:
    self._play_song(client, state, video)

_play_song 主要定义如下:

    def _play_song(self, client, state, song):
        state.now_playing = song
    # Other things are not relevant

1 个答案:

答案 0 :(得分:2)

当您重新加载 cog 时,cog 中的 states 字典将为空。使用 state = self.get_state(ctx.guild) 创建一个新的 GuildState 对象。在 __init__ 类的 GuildState 函数中,self.now_playing 设置为 None

因此,status = state.now_playing.toggle_loop() 将抛出 AttributeError,因为 None 没有属性(在本例中,没有 toggle_loop 属性)。

如果您想消除这些错误,您需要将 self.now_playing 正确设置为具有所需属性的内容。

如果您想保持 states 字典不变,您可以在重新加载 cog 之前保存它并恢复它。以下示例假定 cog 类名为 TestCog

@client.command()
async def reload(ctx):
    temp = client.get_cog('TestCog').states
    client.reload_extension('cog')
    client.get_cog('TestCog').states = temp

请注意,如果您更改 GuildState 的创建方式,这可能会破坏您的齿轮,因为您正在恢复以前版本的 states

相关问题