今天有一个更不寻常的问题,但也许有人可以帮助我。
我正在开发一个机器人,它与音乐有关。以下问题:
如果我更改 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
答案 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
。