【问题标题】:How to properly exec() a coroutine如何正确执行()协程
【发布时间】:2019-09-17 02:47:30
【问题描述】:

我正在编写一个 Discord 机器人,但在测试异步函数时遇到了问题。我想用exec()来测试它,但我似乎无法正确调用该函数。

我尝试了 exec()-ing 函数,无论是否有等待。我查看了API docs,但这并没有让我对我的问题有太多的了解。使用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 python-3.x discord.py


    【解决方案1】:

    asyncawait 有特殊的语法。 await expr 仅在 async def 上下文中正确解析。所以exec("await function()") 将引发SyntaxError,因为exec 通过解析语句并运行它来操作,因此它不尊重事件循环。

    因此,您不能在异步代码中使用exec 来调用异步函数。一旦您了解更多异步函数的工作原理,这就是有意义的,因为 await 比函数调用更能改变代码的行为。

    但是,如果您切换到使用eval,您之前的代码应该返回您正在调用的协程对象。由于协程对象是可等待的,因此您可以像使用 exec 一样使用它。

    所以你应该能够做类似的事情

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

    并让它正常工作。

    【讨论】:

    • 我尝试使用eval,但它会发送相同的语法错误作为消息。 "无效语法(,第 1 行)"
    • 您需要从行首删除await
    • 类似eval(move_message(1, "bot-playground", "admin-test-playground"))?我之前尝试过,它返回协程对象,但不执行。我将更新问题以包含我已经尝试过的内容。
    • 是的,这就是重点。你有协程对象,你需要等待它。所以它就像await eval('move_message(1, "bot-playground", "admin-test-playground")')
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-08
    • 2019-11-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多