运行 仅在用户运行特定命令后才会结束的功能
Run a function which will end only after user runs a certain command
我正在创建一个 Discord 机器人来玩扑克。我有一个函数 wait_for_betting_to_end
定义如下:
def wait_for_betting_to_end():
while not_all_players_have_bet():
pass
我在 cog
中有一个命令 poker
,其中包含以下代码片段:
@commands.command(name='poker')
async def poker(self, ctx):
self.game_started = True
# ...
await preflop()
wait_for_betting_to_end()
# ...
我在 cog
:
中有一个 Discord 命令 bet
@commands.command(name='bet')
async def bet(self, ctx, amt):
if not self.game_started:
print("You're not playing a game.")
return
# does something that would make wait_for_betting_to_end stop
问题是用户在玩扑克时永远无法运行 bet
命令;执行流程永远停留在 wait_for_betting_to_end
中。不播放时,bet
正确显示错误并存在。
我该如何解决这个问题?
您的代码存在的问题是您在 wait_for_betting_to_end()
函数中创建了无限循环。这是一个错误,源于认为 discord.py 使用多线程来获得其异步功能(我可以猜到很多看标签),但事实并非如此。 asyncio
在单个线程中工作,它执行一项任务(如接收消息、处理命令等)并在该任务完成后执行下一个任务,asyncio 的强大之处在于能够暂时 'freeze' 一个没有进展的任务(比如等待响应或只是简单地睡觉)继续下一个任务,并在需要时恢复冻结的任务。 (顺便说一句,我很确定 'freezing' 是完全错误的术语)。您的机器人获得的每个命令都在其自己的任务中处理。你使无限循环永远不会释放扑克任务,所以它阻塞了整个循环。
要解决您的问题,有几种可能性,例如:
而不是无限循环,在你的循环中调用 await asyncio.sleep(0.1)
而不是 pass
,这将允许你的机器人在那个时候从 discord 获取消息,从而对用户的响应做出反应.要停止你的 while 循环,你可以使用一个 self.value ,你可以在需要时将其设置为 False
(在你的 bet 命令中)(也许为此使用带有游戏的字典之类的东西,因为你可能想要 运行同时进行不同的游戏)。
我并没有真正使用 cog,所以我不能自信地为您提供一个可以如何编写代码的示例(至少不会有遗漏一些可以使用 cog 轻松完成的事情的风险)。但我相信这应该会让你走上正确的道路。
我正在创建一个 Discord 机器人来玩扑克。我有一个函数 wait_for_betting_to_end
定义如下:
def wait_for_betting_to_end():
while not_all_players_have_bet():
pass
我在 cog
中有一个命令 poker
,其中包含以下代码片段:
@commands.command(name='poker')
async def poker(self, ctx):
self.game_started = True
# ...
await preflop()
wait_for_betting_to_end()
# ...
我在 cog
:
bet
@commands.command(name='bet')
async def bet(self, ctx, amt):
if not self.game_started:
print("You're not playing a game.")
return
# does something that would make wait_for_betting_to_end stop
问题是用户在玩扑克时永远无法运行 bet
命令;执行流程永远停留在 wait_for_betting_to_end
中。不播放时,bet
正确显示错误并存在。
我该如何解决这个问题?
您的代码存在的问题是您在 wait_for_betting_to_end()
函数中创建了无限循环。这是一个错误,源于认为 discord.py 使用多线程来获得其异步功能(我可以猜到很多看标签),但事实并非如此。 asyncio
在单个线程中工作,它执行一项任务(如接收消息、处理命令等)并在该任务完成后执行下一个任务,asyncio 的强大之处在于能够暂时 'freeze' 一个没有进展的任务(比如等待响应或只是简单地睡觉)继续下一个任务,并在需要时恢复冻结的任务。 (顺便说一句,我很确定 'freezing' 是完全错误的术语)。您的机器人获得的每个命令都在其自己的任务中处理。你使无限循环永远不会释放扑克任务,所以它阻塞了整个循环。
要解决您的问题,有几种可能性,例如:
而不是无限循环,在你的循环中调用 await asyncio.sleep(0.1)
而不是 pass
,这将允许你的机器人在那个时候从 discord 获取消息,从而对用户的响应做出反应.要停止你的 while 循环,你可以使用一个 self.value ,你可以在需要时将其设置为 False
(在你的 bet 命令中)(也许为此使用带有游戏的字典之类的东西,因为你可能想要 运行同时进行不同的游戏)。
我并没有真正使用 cog,所以我不能自信地为您提供一个可以如何编写代码的示例(至少不会有遗漏一些可以使用 cog 轻松完成的事情的风险)。但我相信这应该会让你走上正确的道路。