Как правильно выполнить exec() сопрограмму

Я пишу бота 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

Я хочу, чтобы функция выполнялась правильно, хотя бы что-то печатала. Но ни "хорошо", ни "хорошо!" печатает с тем, что у меня есть сейчас.

Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
1
0
447
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

async и await имеют специальный синтаксис. await expr корректно анализируется только в контексте async def. Таким образом, exec("await function()") вызовет SyntaxError, поскольку exec работает путем разбора оператора и его запуска, поэтому он не учитывает цикл событий.

Поэтому вы не можете использовать exec в асинхронном коде для вызова асинхронных функций. Это имеет смысл, когда вы лучше понимаете, как асинхронные функции работают под капотом, поскольку await изменяет поведение кода больше, чем вызов функции.

Однако, если вы переключитесь на использование eval, код, который у вас был до этого, вместо этого должен возвращать объект сопрограммы, который вы вызываете. Поскольку объекты сопрограммы ожидаемы, вы можете использовать это, как и предполагалось, с exec.

Таким образом, вы должны быть в состоянии сделать что-то вроде

def f(message):
    await eval(message.lstrip('exec '))

и пусть работает корректно.

Я пытался использовать eval, но это отправляет ту же синтаксическую ошибку, что и сообщение. "неверный синтаксис (<строка>, строка 1)"

The Bic Pen 28.04.2019 07:51

Вам нужно будет удалить await с начала строки

Edward Minnix 28.04.2019 07:52

Так что-то вроде eval(move_message(1, "bot-playground", "admin-test-playground"))? Я пробовал это раньше, и он возвращает объект сопрограммы, но не выполняется. Я обновлю вопрос, чтобы включить, что я пробовал это.

The Bic Pen 28.04.2019 08:01

Да, в этом суть. У вас есть объект сопрограммы, и вам нужно ждать его. Так что будет как await eval('move_message(1, "bot-playground", "admin-test-playground")').

Edward Minnix 28.04.2019 08:03

Другие вопросы по теме