【问题标题】:Cannot await in exec无法在 exec 中等待
【发布时间】:2017-08-19 03:41:33
【问题描述】:

嗨,我试图让我的不和谐机器人做我在不和谐客户端输入的内容,我想使用 exec() + 这只是为了测试和实验,所以它是否不安全也没关系。

我的部分代码:

import discord

client = discord.Client()

@client.event
async def on_message(message):
    if message.author == client.user:
        return

    if message.content.startswith('2B: '):
        exec(message.content[4:])   # <--- here is the exec()
    .
    .
    .

但这是我输入时的错误,

2B: await client.send_message(message.channel, 'please stay quiet -.-')

错误:

Ignoring exception in on_message
Traceback (most recent call last):
  File "C:\Users\Shiyon\AppData\Local\Programs\Python\Python36\lib\site-packages\discord\client.py", line 307, in _run_event
    yield from getattr(self, event)(*args, **kwargs)
  File "C:\Users\Shiyon\Desktop\dm_1.py", line 12, in on_message
    exec(message.content[4:])
  File "<string>", line 1
    await client.send_message(message.channel, 'please stay quiet -.-')
               ^
SyntaxError: invalid syntax

【问题讨论】:

    标签: python python-3.x discord discord.py


    【解决方案1】:

    我相信这可能是你的问题:

    请注意,即使在传递给 exec() 函数的代码上下文中,也不得在函数定义之外使用 return 和 yield 语句

    来自https://docs.python.org/3/library/functions.html

    这应该会更好:

    await eval(input)
    

    如果您也希望能够使用非协同程序,您可以在等待 eval 的返回之前进行检查。

    这是来自Rapptz's bot 的 sn-p,它似乎做了你想要的事情:

    @commands.command(pass_context=True, hidden=True)
    @checks.is_owner()
    async def debug(self, ctx, *, code : str):
        """Evaluates code."""
        code = code.strip('` ')
        python = '```py\n{}\n```'
        result = None
    
        env = {
            'bot': self.bot,
            'ctx': ctx,
            'message': ctx.message,
            'server': ctx.message.server,
            'channel': ctx.message.channel,
            'author': ctx.message.author
        }
    
        env.update(globals())
    
        try:
            result = eval(code, env)
            if inspect.isawaitable(result):
                result = await result
        except Exception as e:
            await self.bot.say(python.format(type(e).__name__ + ': ' + str(e)))
            return
    
        await self.bot.say(python.format(result))
    

    解释编辑:

    await 关键字仅在上下文中有效,因为它在循环中暂停执行方面具有一定的魔力。

    exec 函数总是返回 None 并丢失它执行的任何语句的返回值。相比之下,eval 函数返回其语句的返回值。

    client.send_message(...) 返回一个需要在上下文中等待的可等待对象。通过在eval 的返回上使用await,我们可以轻松地做到这一点,并且通过首先检查它是否可以等待我们也可以执行非协程。

    【讨论】:

    • 没有。在这种情况下,错误将更改为:TypeError: object NoneType can't be used in 'await' expression@Blimmo
    • @shiyonsufa 你应该使用eval 而不是exec。由于 python 中的所有内容都会返回一些东西,所以它并没有太大的不同,但允许您处理诸如 await 之类的返回值。
    • 和评估结果 --> await client.send_message(message.channel, '... yes, whats the matter?') ^ SyntaxError: invalid syntax
    • @shiyonsufa 使用命令时不要输入 await。如果您仍然感到困惑,请阅读我添加到答案中的解释。顺便说一句,sn-p 的 try 块就是你真正需要的,剩下的就是用于错误处理等
    • 哇,就是这样。 result = eval(message.content[4:]) await result@Blimmo
    猜你喜欢
    • 1970-01-01
    • 2018-05-31
    • 1970-01-01
    • 1970-01-01
    • 2020-11-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多