Я пишу бота Discord, и у меня возникают проблемы с тестированием асинхронной функции. Я хочу проверить это с помощью exec(), но не могу правильно вызвать функцию.
Я пробовал выполнять функцию exec() как с ожиданием, так и без него. Я просмотрел Документация по API, но это не помогло мне понять мою проблему. Используя eval(), он возвращает объект сопрограммы, но не выполняет его.
exec() выполняется путем обработки сообщения с помощью асинхронной функции.
async def f(message)
#other stuff
...
...
exec(strip2(message.content, "exec"))
return #exec doesn't return anything, so we return to not send an empty message
Асинхронная функция выглядит примерно так:
async def move_message(message_id, old_channel, new_channel):
"""
check the 20 latest messages in old_channel, and if
one of them matches the id, move it to new_channel
"""
print("ok")
async for message in old_channel.history(limit=20):
#do stuff
...
print("good!")
Без ожидания выдает эту ошибку: ...\commands.py:1: RuntimeWarning: coroutine 'move_message' was never awaited
С ожиданием это дает мне SyntaxError:
File "<string>", line 1
await move_message(message, message.channel, "admin-test-playground")
^
SyntaxError: invalid syntax
Я хочу, чтобы функция выполнялась правильно, хотя бы что-то печатала. Но ни "хорошо", ни "хорошо!" печатает с тем, что у меня есть сейчас.






async и await имеют специальный синтаксис. await expr корректно анализируется только в контексте async def. Таким образом, exec("await function()") вызовет SyntaxError, поскольку exec работает путем разбора оператора и его запуска, поэтому он не учитывает цикл событий.
Поэтому вы не можете использовать exec в асинхронном коде для вызова асинхронных функций. Это имеет смысл, когда вы лучше понимаете, как асинхронные функции работают под капотом, поскольку await изменяет поведение кода больше, чем вызов функции.
Однако, если вы переключитесь на использование eval, код, который у вас был до этого, вместо этого должен возвращать объект сопрограммы, который вы вызываете. Поскольку объекты сопрограммы ожидаемы, вы можете использовать это, как и предполагалось, с exec.
Таким образом, вы должны быть в состоянии сделать что-то вроде
def f(message):
await eval(message.lstrip('exec '))
и пусть работает корректно.
Вам нужно будет удалить await с начала строки
Так что-то вроде eval(move_message(1, "bot-playground", "admin-test-playground"))? Я пробовал это раньше, и он возвращает объект сопрограммы, но не выполняется. Я обновлю вопрос, чтобы включить, что я пробовал это.
Да, в этом суть. У вас есть объект сопрограммы, и вам нужно ждать его. Так что будет как await eval('move_message(1, "bot-playground", "admin-test-playground")').
Я пытался использовать
eval, но это отправляет ту же синтаксическую ошибку, что и сообщение. "неверный синтаксис (<строка>, строка 1)"