Я создаю бота Discord для игры в покер. У меня есть функция wait_for_betting_to_end
, которая определяется следующим образом:
def wait_for_betting_to_end():
while not_all_players_have_bet():
pass
У меня есть команда poker
внутри cog
, которая содержит следующий фрагмент кода:
@commands.command(name='poker')
async def poker(self, ctx):
self.game_started = True
# ...
await preflop()
wait_for_betting_to_end()
# ...
У меня есть команда Discord bet
внутри cog
:
@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 проистекает из возможности временно «заморозить» задачу когда прогресс невозможен (например, ожидание ответа или просто сон), чтобы перейти к следующей задаче и возобновить замороженную задачу, когда это необходимо. (Кстати, я почти уверен, что «замораживание» — это совершенно неправильная терминология). Каждая команда, которую получает ваш бот, обрабатывается в отдельной задаче. Вы делаете бесконечный цикл, никогда не освобождаете задачу покера, поэтому он блокирует весь цикл.
Чтобы решить вашу проблему, есть несколько возможностей, например:
Вместо того, чтобы просто бесконечно зацикливаться, вызовите await asyncio.sleep(0.1)
вместо pass
в своем цикле, это позволит вашему боту получать сообщения от раздора за это время и, таким образом, реагировать на ответы ваших пользователей. Чтобы остановить цикл while, вы можете использовать self.value, для которого вы установили значение False
, когда это необходимо (в вашей команде ставок) (возможно, используйте для этого что-то вроде словаря с играми, поскольку вы, вероятно, хотите запускать разные игры одновременно ).
На самом деле я не работаю с Cog, поэтому я не могу с уверенностью дать вам проработанный пример того, как вы могли бы сделать свой код (по крайней мере, не рискуя упустить что-то, что можно легко сделать с помощью Cogs). Но это должно поставить вас на правильный путь, я считаю.